WindowLayout.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  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 3 of the License, or
  8. ** (at your option) 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 this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: WindowLayout.cpp /////////////////////////////////////////////////////////////////////////
  24. // Created: Colin Day, September 2001
  25. // Desc: Layouts for grouping windows together
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "GameClient/WindowLayout.h"
  30. #include "GameClient/Shell.h"
  31. #include "GameClient/GameWindowManager.h"
  32. #ifdef _INTERNAL
  33. // for occasional debugging...
  34. //#pragma optimize("", off)
  35. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  36. #endif
  37. // PUBLIC FUNCTIONS ///////////////////////////////////////////////////////////////////////////////
  38. //-------------------------------------------------------------------------------------------------
  39. //-------------------------------------------------------------------------------------------------
  40. WindowLayout::WindowLayout( void )
  41. {
  42. m_filenameString.set("EmptyLayout");
  43. m_windowList = NULL;
  44. m_windowTail = NULL;
  45. m_windowCount = 0;
  46. m_hidden = FALSE;
  47. m_init = NULL;
  48. m_update = NULL;
  49. m_shutdown = NULL;
  50. } // end WindowLayout
  51. //-------------------------------------------------------------------------------------------------
  52. //-------------------------------------------------------------------------------------------------
  53. WindowLayout::~WindowLayout( void )
  54. {
  55. //
  56. // it is the users responsability to remove windows from the layout beforing destroying the
  57. // layout itself. This allows for maximum flexibility of the window layouts and you can
  58. // use them in any you see fit, as long as they are clean when they go away
  59. //
  60. DEBUG_ASSERTCRASH( m_windowList == NULL, ("Window layout being destroyed still has window references") );
  61. DEBUG_ASSERTCRASH( m_windowTail == NULL, ("Window layout being destroyed still has window references") );
  62. } // end ~WindowLayout
  63. //-------------------------------------------------------------------------------------------------
  64. /** Set the hidden/visible status of all the windows in this layout */
  65. //-------------------------------------------------------------------------------------------------
  66. void WindowLayout::hide( Bool hide )
  67. {
  68. GameWindow *window;
  69. // hide or unhide all windows in this layout
  70. for( window = m_windowList; window; window = window->winGetNextInLayout() )
  71. {
  72. window->winHide( hide );
  73. } // end for window
  74. // save the new visible state of the system
  75. m_hidden = hide;
  76. } // end hide
  77. //-------------------------------------------------------------------------------------------------
  78. /** Add window to this layout */
  79. //-------------------------------------------------------------------------------------------------
  80. void WindowLayout::addWindow( GameWindow *window )
  81. {
  82. GameWindow *win = findWindow( window );
  83. // only add window if window is not in this layout already
  84. if( win == NULL )
  85. {
  86. DEBUG_ASSERTCRASH( window->winGetNextInLayout() == NULL,
  87. ("NextInLayout should be NULL before adding") );
  88. DEBUG_ASSERTCRASH( window->winGetPrevInLayout() == NULL,
  89. ("PrevInLayout should be NULL before adding") );
  90. window->winSetPrevInLayout( NULL );
  91. window->winSetNextInLayout( m_windowList );
  92. if( m_windowList )
  93. m_windowList->winSetPrevInLayout( window );
  94. m_windowList = window;
  95. // set layout into window
  96. window->winSetLayout( this );
  97. // if no tail pointer, this is it
  98. if( m_windowTail == NULL )
  99. m_windowTail = window;
  100. // we gots another window now
  101. m_windowCount++;
  102. } // end if
  103. } // end addWindow
  104. //-------------------------------------------------------------------------------------------------
  105. /** Remove window from this layout */
  106. //-------------------------------------------------------------------------------------------------
  107. void WindowLayout::removeWindow( GameWindow *window )
  108. {
  109. GameWindow *win = findWindow( window );
  110. // can't remove window unless it's really part of this layout
  111. if( win )
  112. {
  113. GameWindow *prev, *next;
  114. prev = win->winGetPrevInLayout();
  115. next = win->winGetNextInLayout();
  116. if( next )
  117. next->winSetPrevInLayout( prev );
  118. if( prev )
  119. prev->winSetNextInLayout( next );
  120. else
  121. m_windowList = next;
  122. // set window as having no layout info
  123. win->winSetLayout( NULL );
  124. win->winSetNextInLayout( NULL );
  125. win->winSetPrevInLayout( NULL );
  126. // if we removed the tail, set the new tail
  127. if( m_windowTail == win )
  128. m_windowTail = prev;
  129. // we lost one sir!
  130. m_windowCount--;
  131. } // end if
  132. } // end removeWindow
  133. //-------------------------------------------------------------------------------------------------
  134. /** Destroy all the windows in a layout */
  135. //-------------------------------------------------------------------------------------------------
  136. void WindowLayout::destroyWindows( void )
  137. {
  138. if (this == NULL)
  139. {
  140. return;
  141. }
  142. GameWindow *window;
  143. while( (window = getFirstWindow()) != 0 )
  144. {
  145. // remove window from this layout
  146. removeWindow( window );
  147. // destroy window in window system
  148. TheWindowManager->winDestroy( window );
  149. } // end while
  150. } // end destroyWindows
  151. //-------------------------------------------------------------------------------------------------
  152. /** Create the windows using the .wnd file script and load all windows into
  153. * this layout */
  154. //-------------------------------------------------------------------------------------------------
  155. Bool WindowLayout::load( AsciiString filename )
  156. {
  157. // sanity
  158. if( filename.isEmpty() )
  159. return FALSE;
  160. //
  161. // when we create new windows they are always placed on the top
  162. // of the window stack. The load layout from script will return the
  163. // FIRST window loaded from the script, if we traverse from the head of
  164. // the window list till we see that window returned from the layout
  165. // loader, that will be all the root windows loaded from the .wnd file
  166. //
  167. GameWindow *target;
  168. WindowLayoutInfo info;
  169. target = TheWindowManager->winCreateFromScript( filename, &info );
  170. if( target == NULL )
  171. {
  172. DEBUG_ASSERTCRASH( target, ("WindowLayout::load - Failed to load layout") );
  173. DEBUG_LOG(( "WindowLayout::load - Unable to load layout file '%s'\n", filename.str() ));
  174. return FALSE;
  175. } // end if
  176. //
  177. // add windows loaded from .wnd file to the layout, via info.windows.
  178. //
  179. std::list<GameWindow *>::iterator it;
  180. for (it = info.windows.begin(); it != info.windows.end(); ++it)
  181. {
  182. // add window to this layout
  183. addWindow( *it );
  184. }
  185. /* MDC - can't do this, as modal windows will be at the head...
  186. //
  187. // add windows loaded from .wnd file to the layout, note we start at
  188. // target and go backwards as the layout->addWindow() puts at top
  189. // of list and will therefore reverse the order
  190. //
  191. GameWindow *window;
  192. for( window = target; window; window = window->winGetPrev() )
  193. {
  194. // add window to this layout
  195. addWindow( window );
  196. } // end for window
  197. */
  198. // copy filename
  199. m_filenameString = filename;
  200. // assign script info to the layout
  201. setInit( info.init );
  202. setUpdate( info.update );
  203. setShutdown( info.shutdown );
  204. return TRUE; // success
  205. } // end load
  206. //-------------------------------------------------------------------------------------------------
  207. /** Bring all windows in this layout forward */
  208. //-------------------------------------------------------------------------------------------------
  209. void WindowLayout::bringForward( void )
  210. {
  211. //
  212. // loop through all our windows and bring each of them to the top of
  213. // the window stack, note that we are getting a prev pointer because the
  214. // action of bringing a window to the top of the stack does detach it
  215. // from the window list and the layout window list ... it is then
  216. // re-attached at the top. Also note, to preserve the ordering of
  217. // the windows we pull from the tail and add to the top
  218. //
  219. GameWindow *window, *prev;
  220. Int countLeft = m_windowCount;
  221. for( window = m_windowTail; countLeft; window = prev )
  222. {
  223. DEBUG_ASSERTCRASH( window, ("Must have window: m_windowCount is off") );
  224. prev = window->winGetPrevInLayout();
  225. window->winBringToTop();
  226. countLeft--;
  227. } // end for window
  228. } // end bringForward
  229. // PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////////////////////
  230. //-------------------------------------------------------------------------------------------------
  231. /** Find window within this layout */
  232. //-------------------------------------------------------------------------------------------------
  233. GameWindow *WindowLayout::findWindow( GameWindow *window )
  234. {
  235. GameWindow *win;
  236. for( win = m_windowList; win; win = win->winGetNextInLayout() )
  237. if( win == window )
  238. return win;
  239. return NULL; // window not found
  240. } // end findWindow