/* ** Command & Conquer Generals Zero Hour(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ //////////////////////////////////////////////////////////////////////////////// // // // (c) 2001-2003 Electronic Arts Inc. // // // //////////////////////////////////////////////////////////////////////////////// // FILE: RadioButton.cpp ////////////////////////////////////////////////////// //----------------------------------------------------------------------------- // // Westwood Studios Pacific. // // Confidential Information // Copyright (C) 2001 - All Rights Reserved // //----------------------------------------------------------------------------- // // Project: RTS3 // // File name: \projects\RTS\code\gameengine\Source\GameClient\GUI\Gadget\GadgetTabControl.cpp // // Created: Graham Smallwood, November 2001 // // Desc: Tab Set GUI control // //----------------------------------------------------------------------------- /////////////////////////////////////////////////////////////////////////////// // SYSTEM INCLUDES //////////////////////////////////////////////////////////// #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine // USER INCLUDES ////////////////////////////////////////////////////////////// #include "Common/Language.h" #include "Gameclient/GameWindowManager.h" #include "GameClient/Gadget.h" #include "GameClient/GadgetTabControl.h" // DEFINES //////////////////////////////////////////////////////////////////// // PRIVATE TYPES ////////////////////////////////////////////////////////////// // PRIVATE DATA /////////////////////////////////////////////////////////////// // PUBLIC DATA //////////////////////////////////////////////////////////////// // PRIVATE PROTOTYPES ///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// // GadgetTabControlInput ===================================================== /** Handle input for TabControl */ //============================================================================= WindowMsgHandledType GadgetTabControlInput( GameWindow *tabControl, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) { // WinInstanceData *instData = tabControl->winGetInstanceData(); TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); Int tabX, tabY; tabControl->winGetScreenPosition( &tabX, &tabY ); Int mouseX = LOLONGTOSHORT(mData1) - tabX;//mData1 is packedMouseCoords in screen space Int mouseY = HILONGTOSHORT(mData1) - tabY; Int tabsLeft = tabData->tabsLeftLimit; Int tabsRight = tabData->tabsRightLimit; Int tabsBottom = tabData->tabsBottomLimit; Int tabsTop = tabData->tabsTopLimit; switch( msg ) { case GWM_LEFT_DOWN: { if( (mouseX < tabsLeft) || (mouseX > tabsRight) || (mouseY < tabsTop) || (mouseY > tabsBottom) ) {//I eat input on myself that isn't a tab (a button click would mean I don't see the input ever.) return MSG_HANDLED; } Int distanceIn; Int tabSize; if( (tabData->tabEdge == TP_RIGHT_SIDE) || (tabData->tabEdge == TP_LEFT_SIDE) ) {//scan down to find which button distanceIn = mouseY - tabsTop; tabSize = tabData->tabHeight; } else {//scan right to find which button distanceIn = mouseX - tabsLeft; tabSize = tabData->tabWidth; } Int tabPressed = distanceIn / tabSize; if( ! tabData->subPaneDisabled[tabPressed] && (tabPressed != tabData->activeTab) ) GadgetTabControlShowSubPane( tabControl, tabPressed ); } default: { return MSG_IGNORED; } } return MSG_HANDLED; } // end GadgetTabControlInput // GadgetTabControlSystem ==================================================== /** Handle system messages for TabControl */ //============================================================================= WindowMsgHandledType GadgetTabControlSystem( GameWindow *tabControl, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2 ) { switch( msg ) { // ------------------------------------------------------------------------ case GWM_CREATE: break; // ------------------------------------------------------------------------ case GWM_DESTROY: { TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); // free tab control user data delete tabData; break; } // end destroy case GGM_RESIZED: {//On resize, we need to upkeep the pane sizes and tabs since they are bound to us GadgetTabControlResizeSubPanes( tabControl ); GadgetTabControlComputeTabRegion( tabControl ); break; } case GBM_SELECTED: {//Pass buttons messages up GameWindow *parent = tabControl->winGetParent(); if( parent ) return TheWindowManager->winSendSystemMsg( parent, msg, mData1, mData2 ); } default: return MSG_IGNORED; } // end switch( msg ) return MSG_HANDLED; } // end GadgetTabControlSystem void GadgetTabControlComputeTabRegion( GameWindow *tabControl )///< Recalc the tab positions based on userData { Int winWidth, winHeight; tabControl->winGetSize( &winWidth, &winHeight ); TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); Int horzOffset = 0, vertOffset = 0; if( (tabData->tabEdge == TP_TOP_SIDE) || (tabData->tabEdge == TP_BOTTOM_SIDE) ) { if( tabData->tabOrientation == TP_CENTER ) { horzOffset = winWidth - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabWidth ); horzOffset /= 2; } else if( tabData->tabOrientation == TP_BOTTOMRIGHT ) { horzOffset = winWidth - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabWidth ); } else if( tabData->tabOrientation == TP_TOPLEFT ) { horzOffset = 0; } } else { if( tabData->tabOrientation == TP_CENTER ) { vertOffset = winHeight - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabHeight ); vertOffset /= 2; } else if( tabData->tabOrientation == TP_BOTTOMRIGHT ) { vertOffset = winHeight - ( 2 * tabData->paneBorder ) - ( tabData->tabCount * tabData->tabHeight ); } else if( tabData->tabOrientation == TP_TOPLEFT ) { vertOffset = 0; } } if( tabData->tabEdge == TP_TOP_SIDE ) { tabData->tabsTopLimit = tabData->paneBorder; tabData->tabsBottomLimit = tabData->paneBorder + tabData->tabHeight; tabData->tabsLeftLimit = tabData->paneBorder + horzOffset; tabData->tabsRightLimit = tabData->paneBorder + horzOffset + ( tabData->tabWidth * tabData->tabCount ); } else if( tabData->tabEdge == TP_BOTTOM_SIDE ) { tabData->tabsTopLimit = winHeight - tabData->paneBorder - tabData->tabHeight; tabData->tabsBottomLimit = winHeight - tabData->paneBorder; tabData->tabsLeftLimit = tabData->paneBorder + horzOffset; tabData->tabsRightLimit = tabData->paneBorder + horzOffset + ( tabData->tabWidth * tabData->tabCount ); } else if( tabData->tabEdge == TP_RIGHT_SIDE ) { tabData->tabsLeftLimit = winWidth - tabData->paneBorder - tabData->tabWidth; tabData->tabsRightLimit = winWidth - tabData->paneBorder; tabData->tabsTopLimit = tabData->paneBorder + vertOffset; tabData->tabsBottomLimit = tabData->paneBorder + vertOffset + ( tabData->tabHeight * tabData->tabCount ); } else if( tabData->tabEdge == TP_LEFT_SIDE ) { tabData->tabsLeftLimit = tabData->paneBorder; tabData->tabsRightLimit = tabData->paneBorder + tabData->tabWidth; tabData->tabsTopLimit = tabData->paneBorder + vertOffset; tabData->tabsBottomLimit = tabData->paneBorder + vertOffset + ( tabData->tabHeight * tabData->tabCount ); } } void GadgetTabControlComputeSubPaneSize( GameWindow *tabControl, Int *width, Int *height, Int *x, Int *y ) { Int winWidth, winHeight; tabControl->winGetSize( &winWidth, &winHeight ); TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); if( (tabData->tabEdge == TP_TOP_SIDE) || (tabData->tabEdge == TP_BOTTOM_SIDE) ) *height = winHeight - (2 * tabData->paneBorder) - tabData->tabHeight; else *height = winHeight - (2 * tabData->paneBorder); if( (tabData->tabEdge == TP_LEFT_SIDE) || (tabData->tabEdge == TP_RIGHT_SIDE) ) *width = winWidth - (2 * tabData->paneBorder) - tabData->tabWidth; else *width = winWidth - (2 * tabData->paneBorder); if( tabData->tabEdge == TP_LEFT_SIDE ) *x = tabData->paneBorder + tabData->tabWidth; else *x = tabData->paneBorder; if( tabData->tabEdge == TP_TOP_SIDE ) *y = tabData->paneBorder + tabData->tabHeight; else *y = tabData->paneBorder; } void GadgetTabControlShowSubPane( GameWindow *tabControl, Int whichPane) { TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ ) { if( tabData->subPanes[paneIndex] != NULL ) tabData->subPanes[paneIndex]->winHide( true ); } if( tabData->subPanes[whichPane] ) tabData->activeTab = whichPane; else tabData->activeTab = 0; tabData->activeTab = min( tabData->activeTab, tabData->tabCount - 1 ); tabData->subPanes[tabData->activeTab]->winHide( false ); } void GadgetTabControlCreateSubPanes( GameWindow *tabControl )///< Create User Windows attached to userData as Panes {//These two funcs are called after all the Editor set data is updated TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); Int width, height, x, y; GadgetTabControlComputeSubPaneSize(tabControl, &width, &height, &x, &y); for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ ) { if( (tabData->subPanes[paneIndex] == NULL) )//This one is blank { tabData->subPanes[paneIndex] = TheWindowManager->winCreate( tabControl, WIN_STATUS_NONE, x, y, width, height, PassSelectedButtonsToParentSystem, NULL); WinInstanceData *instData = tabData->subPanes[paneIndex]->winGetInstanceData(); BitSet( instData->m_style, GWS_TAB_PANE ); char buffer[20]; sprintf( buffer, "Pane %d", paneIndex ); instData->m_decoratedNameString = buffer; //set enabled status to that of Parent tabData->subPanes[paneIndex]->winEnable( BitTest(tabControl->winGetStatus(), WIN_STATUS_ENABLED) ); } else//this one exists, tabCount will control keeping extra panes perma-hidden { tabData->subPanes[paneIndex]->winSetSize( width, height ); tabData->subPanes[paneIndex]->winSetPosition( x, y ); } } GadgetTabControlShowSubPane( tabControl, tabData->activeTab ); } void GadgetTabControlResizeSubPanes( GameWindow *tabControl ) { TabControlData *tabData = (TabControlData *)tabControl->winGetUserData(); Int width, height, x, y; GadgetTabControlComputeSubPaneSize(tabControl, &width, &height, &x, &y); for( Int paneIndex = 0; paneIndex < NUM_TAB_PANES; paneIndex++ ) { if( tabData->subPanes[paneIndex] ) { tabData->subPanes[paneIndex]->winSetSize( width, height ); tabData->subPanes[paneIndex]->winSetPosition( x, y ); } } } ///winGetUserData(); GameWindow *child = tabControl->winGetChild(); if( child ) {//need to write down children, and they are reversed from our array while( child->winGetNext() != NULL ) { child = child->winGetNext(); } while( child ) { tabData->subPanes[childIndex] = child; childIndex++; child = child->winGetPrev(); } } }