00001 #include "mythscreenstack.h"
00002 #include "mythmainwindow.h"
00003 #include "mythscreentype.h"
00004 #include "mythpainter.h"
00005
00006 #include <iostream>
00007 #include <cassert>
00008 using namespace std;
00009
00010 #include <qobjectlist.h>
00011 #include <qapplication.h>
00012
00013 const int kFadeVal = 10;
00014
00015 MythScreenStack::MythScreenStack(MythMainWindow *parent, const char *name,
00016 bool mainstack)
00017 : QObject(parent, name)
00018 {
00019 assert(parent);
00020
00021 parent->AddScreenStack(this, mainstack);
00022
00023 newTop = NULL;
00024 topScreen = NULL;
00025
00026 m_DoTransitions = (GetMythPainter()->SupportsAlpha() &&
00027 GetMythPainter()->SupportsAnimation());
00028 m_InNewTransition = false;
00029 }
00030
00031 MythScreenStack::~MythScreenStack()
00032 {
00033 }
00034
00035 int MythScreenStack::TotalScreens(void)
00036 {
00037 return m_Children.count();
00038 }
00039
00040 void MythScreenStack::AddScreen(MythScreenType *screen, bool allowFade)
00041 {
00042 if (!screen)
00043 return;
00044
00045 qApp->lock();
00046
00047 MythScreenType *old = topScreen;
00048 if (old)
00049 old->aboutToHide();
00050
00051 m_Children.push_back(screen);
00052
00053 if (allowFade && m_DoTransitions)
00054 {
00055 newTop = screen;
00056 DoNewFadeTransition();
00057 }
00058 else
00059 {
00060 reinterpret_cast<MythMainWindow *>(parent())->update();
00061 RecalculateDrawOrder();
00062 }
00063
00064 screen->aboutToShow();
00065
00066 topScreen = screen;
00067
00068 qApp->unlock();
00069 }
00070
00071 void MythScreenStack::PopScreen(bool allowFade)
00072 {
00073 if (m_Children.isEmpty())
00074 return;
00075
00076 MythScreenType *top = topScreen;
00077
00078 if (!top || top->IsDeleting())
00079 return;
00080
00081 MythMainWindow *mainwindow = GetMythMainWindow();
00082
00083 qApp->lock();
00084
00085 removeChild(top);
00086 if (allowFade && m_DoTransitions && !mainwindow->IsExitingToMain())
00087 {
00088 top->SetFullscreen(false);
00089 top->SetDeleting(true);
00090 m_ToDelete.push_back(top);
00091 top->AdjustAlpha(1, -kFadeVal);
00092 }
00093 else
00094 {
00095 m_Children.pop_back();
00096 delete top;
00097 top = NULL;
00098
00099 mainwindow->update();
00100 if (mainwindow->IsExitingToMain())
00101 QApplication::postEvent(mainwindow, new ExitToMainMenuEvent());
00102 }
00103
00104 topScreen = NULL;
00105
00106 RecalculateDrawOrder();
00107
00108
00109 if (top)
00110 m_DrawOrder.push_back(top);
00111
00112 if (!m_Children.isEmpty())
00113 {
00114 QValueVector<MythScreenType *>::Iterator it;
00115 for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
00116 {
00117 if (*it != top && !(*it)->IsDeleting())
00118 {
00119 topScreen = (*it);
00120 if (m_DoTransitions)
00121 {
00122 (*it)->SetAlpha(0);
00123 (*it)->AdjustAlpha(1, kFadeVal);
00124 }
00125 (*it)->aboutToShow();
00126 }
00127 }
00128 }
00129
00130 if (topScreen)
00131 topScreen->SetRedraw();
00132
00133 qApp->unlock();
00134 }
00135
00136 MythScreenType *MythScreenStack::GetTopScreen(void)
00137 {
00138 if (topScreen)
00139 return topScreen;
00140 if (!m_DrawOrder.isEmpty())
00141 return m_DrawOrder.back();
00142 return NULL;
00143 }
00144
00145 void MythScreenStack::GetDrawOrder(QValueVector<MythScreenType *> &screens)
00146 {
00147 if (m_InNewTransition)
00148 CheckNewFadeTransition();
00149 CheckDeletes();
00150
00151 screens = m_DrawOrder;
00152 }
00153
00154 void MythScreenStack::RecalculateDrawOrder(void)
00155 {
00156 m_DrawOrder.clear();
00157
00158 if (m_Children.isEmpty())
00159 return;
00160
00161 QValueVector<MythScreenType *>::Iterator it;
00162
00163 for (it = m_Children.begin(); it != m_Children.end(); ++it)
00164 {
00165 MythScreenType *screen = (*it);
00166
00167 if (screen->IsFullscreen())
00168 m_DrawOrder.clear();
00169
00170 m_DrawOrder.push_back(screen);
00171 }
00172
00173 if (m_DrawOrder.isEmpty())
00174 {
00175 MythScreenType *screen = GetTopScreen();
00176 if (screen)
00177 m_DrawOrder.push_back(screen);
00178 }
00179 }
00180
00181 void MythScreenStack::DoNewFadeTransition(void)
00182 {
00183 m_InNewTransition = true;
00184 newTop->SetAlpha(0);
00185 newTop->AdjustAlpha(1, kFadeVal);
00186
00187 if (newTop->IsFullscreen())
00188 {
00189 QValueVector<MythScreenType *>::Iterator it;
00190 for (it = m_DrawOrder.begin(); it != m_DrawOrder.end(); ++it)
00191 {
00192 if (!(*it)->IsDeleting())
00193 (*it)->AdjustAlpha(1, -kFadeVal);
00194 }
00195
00196 m_DrawOrder.push_back(newTop);
00197 }
00198 else
00199 RecalculateDrawOrder();
00200 }
00201
00202 void MythScreenStack::CheckNewFadeTransition(void)
00203 {
00204 if (!newTop)
00205 {
00206 m_InNewTransition = false;
00207 return;
00208 }
00209
00210 if (newTop->GetAlpha() >= 255)
00211 {
00212 m_InNewTransition = false;
00213 newTop = NULL;
00214
00215 RecalculateDrawOrder();
00216 }
00217 }
00218
00219 void MythScreenStack::CheckDeletes(void)
00220 {
00221 if (m_ToDelete.isEmpty())
00222 return;
00223
00224 bool changed = false;
00225
00226 QValueVector<MythScreenType *>::Iterator it = m_ToDelete.begin();
00227 while (it != m_ToDelete.end() && !m_ToDelete.isEmpty())
00228 {
00229 bool deleteit = false;
00230
00231 if ((*it)->GetAlpha() <= 0)
00232 {
00233 deleteit = true;
00234 }
00235
00236 if (!deleteit)
00237 {
00238 bool found = false;
00239
00240 QValueVector<MythScreenType *>::Iterator test;
00241 for (test = m_DrawOrder.begin(); test != m_DrawOrder.end(); ++test)
00242 {
00243 if (*it == *test)
00244 {
00245 found = true;
00246 break;
00247 }
00248 }
00249
00250 if (!found)
00251 deleteit = true;
00252 }
00253
00254 if (deleteit)
00255 {
00256 QValueVector<MythScreenType *>::Iterator test;
00257 for (test = m_Children.begin(); test != m_Children.end(); ++test)
00258 {
00259 if (*test == *it)
00260 {
00261 m_Children.erase(test);
00262 break;
00263 }
00264 }
00265
00266 if (*it == newTop)
00267 newTop = NULL;
00268 delete (*it);
00269 m_ToDelete.erase(it);
00270 it = m_ToDelete.begin();
00271 changed = true;
00272 continue;
00273 }
00274
00275 ++it;
00276 }
00277
00278 if (changed)
00279 {
00280 RecalculateDrawOrder();
00281 }
00282 }