2023-10-19 16:19:09 +02:00
/*
* CIntObject . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
# include "StdInc.h"
# include "CIntObject.h"
# include "CGuiHandler.h"
# include "WindowHandler.h"
# include "EventDispatcher.h"
# include "Shortcut.h"
# include "../render/Canvas.h"
# include "../windows/CMessage.h"
# include "../CMT.h"
CIntObject : : CIntObject ( int used_ , Point pos_ ) :
parent_m ( nullptr ) ,
parent ( parent_m ) ,
redrawParent ( false ) ,
inputEnabled ( true ) ,
used ( used_ ) ,
2024-08-09 14:26:53 +00:00
recActions ( ALL_ACTIONS ) ,
2023-10-19 16:19:09 +02:00
pos ( pos_ , Point ( ) )
{
if ( GH . captureChildren )
GH . createdObj . front ( ) - > addChild ( this , true ) ;
}
CIntObject : : ~ CIntObject ( )
{
if ( isActive ( ) )
deactivate ( ) ;
while ( ! children . empty ( ) )
2024-08-09 15:50:37 +00:00
removeChild ( children . front ( ) ) ;
2023-10-19 16:19:09 +02:00
if ( parent_m )
parent_m - > removeChild ( this ) ;
}
void CIntObject : : show ( Canvas & to )
{
2024-08-09 14:26:53 +00:00
for ( auto & elem : children )
if ( elem - > recActions & UPDATE )
elem - > show ( to ) ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : showAll ( Canvas & to )
{
2024-08-09 14:26:53 +00:00
for ( auto & elem : children )
if ( elem - > recActions & SHOWALL )
elem - > showAll ( to ) ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : activate ( )
{
if ( isActive ( ) )
return ;
if ( inputEnabled )
activateEvents ( used | GENERAL ) ;
else
activateEvents ( GENERAL ) ;
assert ( isActive ( ) ) ;
2024-08-09 14:26:53 +00:00
for ( auto & elem : children )
if ( elem - > recActions & ACTIVATE )
elem - > activate ( ) ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : deactivate ( )
{
if ( ! isActive ( ) )
return ;
deactivateEvents ( used | GENERAL ) ;
assert ( ! isActive ( ) ) ;
2024-08-09 14:26:53 +00:00
for ( auto & elem : children )
if ( elem - > recActions & DEACTIVATE )
elem - > deactivate ( ) ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : addUsedEvents ( ui16 newActions )
{
if ( isActive ( ) & & inputEnabled )
activateEvents ( ~ used & newActions ) ;
used | = newActions ;
}
void CIntObject : : removeUsedEvents ( ui16 newActions )
{
if ( isActive ( ) )
deactivateEvents ( used & newActions ) ;
used & = ~ newActions ;
}
void CIntObject : : disable ( )
{
if ( isActive ( ) )
deactivate ( ) ;
2024-08-09 16:11:07 +00:00
recActions = NO_ACTIONS ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : enable ( )
{
if ( ! isActive ( ) & & ( ! parent_m | | parent_m - > isActive ( ) ) )
{
activate ( ) ;
redraw ( ) ;
}
2024-08-09 16:11:07 +00:00
recActions = ALL_ACTIONS ;
2023-10-19 16:19:09 +02:00
}
void CIntObject : : setEnabled ( bool on )
{
if ( on )
enable ( ) ;
else
disable ( ) ;
}
void CIntObject : : setInputEnabled ( bool on )
{
if ( inputEnabled = = on )
return ;
inputEnabled = on ;
if ( isActive ( ) )
{
assert ( ( used & GENERAL ) = = 0 ) ;
if ( on )
activateEvents ( used ) ;
else
deactivateEvents ( used ) ;
}
for ( auto & elem : children )
elem - > setInputEnabled ( on ) ;
}
void CIntObject : : setRedrawParent ( bool on )
{
redrawParent = on ;
}
void CIntObject : : fitToScreen ( int borderWidth , bool propagate )
2024-08-17 12:25:16 +02:00
{
fitToRect ( Rect ( Point ( 0 , 0 ) , GH . screenDimensions ( ) ) , borderWidth , propagate ) ;
}
void CIntObject : : fitToRect ( Rect rect , int borderWidth , bool propagate )
2023-10-19 16:19:09 +02:00
{
Point newPos = pos . topLeft ( ) ;
2024-08-17 12:25:16 +02:00
vstd : : amax ( newPos . x , rect . x + borderWidth ) ;
vstd : : amax ( newPos . y , rect . y + borderWidth ) ;
vstd : : amin ( newPos . x , rect . x + rect . w - borderWidth - pos . w ) ;
vstd : : amin ( newPos . y , rect . y + rect . h - borderWidth - pos . h ) ;
2023-10-19 16:19:09 +02:00
if ( newPos ! = pos . topLeft ( ) )
moveTo ( newPos , propagate ) ;
}
void CIntObject : : moveBy ( const Point & p , bool propagate )
{
pos . x + = p . x ;
pos . y + = p . y ;
if ( propagate )
for ( auto & elem : children )
elem - > moveBy ( p , propagate ) ;
}
void CIntObject : : moveTo ( const Point & p , bool propagate )
{
moveBy ( Point ( p . x - pos . x , p . y - pos . y ) , propagate ) ;
}
void CIntObject : : addChild ( CIntObject * child , bool adjustPosition )
{
if ( vstd : : contains ( children , child ) )
{
return ;
}
if ( child - > parent_m )
{
child - > parent_m - > removeChild ( child , adjustPosition ) ;
}
children . push_back ( child ) ;
child - > parent_m = this ;
if ( adjustPosition )
child - > moveBy ( pos . topLeft ( ) , adjustPosition ) ;
if ( inputEnabled ! = child - > inputEnabled )
child - > setInputEnabled ( inputEnabled ) ;
if ( ! isActive ( ) & & child - > isActive ( ) )
child - > deactivate ( ) ;
if ( isActive ( ) & & ! child - > isActive ( ) )
child - > activate ( ) ;
}
void CIntObject : : removeChild ( CIntObject * child , bool adjustPosition )
{
if ( ! child )
return ;
if ( ! vstd : : contains ( children , child ) )
throw std : : runtime_error ( " Wrong child object " ) ;
if ( child - > parent_m ! = this )
throw std : : runtime_error ( " Wrong child object " ) ;
children - = child ;
child - > parent_m = nullptr ;
if ( adjustPosition )
child - > pos - = pos . topLeft ( ) ;
}
void CIntObject : : redraw ( )
{
//currently most of calls come from active objects so this check won't affect them
//it should fix glitches when called by inactive elements located below active window
if ( isActive ( ) )
{
if ( parent_m & & redrawParent )
{
parent_m - > redraw ( ) ;
}
else
{
2024-07-22 11:00:45 +00:00
Canvas buffer = Canvas : : createFromSurface ( screenBuf , CanvasScalingPolicy : : AUTO ) ;
2023-10-19 16:19:09 +02:00
showAll ( buffer ) ;
if ( screenBuf ! = screen )
{
2024-07-22 11:00:45 +00:00
Canvas screenBuffer = Canvas : : createFromSurface ( screen , CanvasScalingPolicy : : AUTO ) ;
2023-10-19 16:19:09 +02:00
showAll ( screenBuffer ) ;
}
}
}
}
2024-08-03 17:04:27 +03:00
void CIntObject : : moveChildForeground ( const CIntObject * childToMove )
{
for ( auto child = children . begin ( ) ; child ! = children . end ( ) ; child + + )
if ( * child = = childToMove & & child ! = children . end ( ) )
{
std : : rotate ( child , child + 1 , children . end ( ) ) ;
}
}
2023-10-19 16:19:09 +02:00
bool CIntObject : : receiveEvent ( const Point & position , int eventType ) const
{
return pos . isInside ( position ) ;
}
const Rect & CIntObject : : getPosition ( ) const
{
return pos ;
}
void CIntObject : : onScreenResize ( )
{
center ( pos , true ) ;
}
bool CIntObject : : isPopupWindow ( ) const
{
return false ;
}
const Rect & CIntObject : : center ( const Rect & r , bool propagate )
{
pos . w = r . w ;
pos . h = r . h ;
return center ( Point ( GH . screenDimensions ( ) . x / 2 , GH . screenDimensions ( ) . y / 2 ) , propagate ) ;
}
const Rect & CIntObject : : center ( bool propagate )
{
return center ( pos , propagate ) ;
}
const Rect & CIntObject : : center ( const Point & p , bool propagate )
{
moveBy ( Point ( p . x - pos . w / 2 - pos . x ,
p . y - pos . h / 2 - pos . y ) ,
propagate ) ;
return pos ;
}
bool CIntObject : : captureThisKey ( EShortcut key )
{
return false ;
}
CKeyShortcut : : CKeyShortcut ( )
: assignedKey ( EShortcut : : NONE )
, shortcutPressed ( false )
{ }
CKeyShortcut : : CKeyShortcut ( EShortcut key )
: assignedKey ( key )
, shortcutPressed ( false )
{
}
void CKeyShortcut : : keyPressed ( EShortcut key )
{
if ( assignedKey = = key & & assignedKey ! = EShortcut : : NONE & & ! shortcutPressed )
{
shortcutPressed = true ;
clickPressed ( GH . getCursorPosition ( ) ) ;
}
}
void CKeyShortcut : : keyReleased ( EShortcut key )
{
if ( assignedKey = = key & & assignedKey ! = EShortcut : : NONE & & shortcutPressed )
{
shortcutPressed = false ;
clickReleased ( GH . getCursorPosition ( ) ) ;
}
}
WindowBase : : WindowBase ( int used_ , Point pos_ )
: CIntObject ( used_ , pos_ )
{
}
void WindowBase : : close ( )
{
if ( ! GH . windows ( ) . isTopWindow ( this ) )
2025-01-19 12:39:22 +00:00
{
auto topWindow = GH . windows ( ) . topWindow < IShowActivatable > ( ) . get ( ) ;
throw std : : runtime_error ( std : : string ( " Only top interface can be closed! Top window is " ) + typeid ( * this ) . name ( ) + " but attempted to close " + typeid ( * topWindow ) . name ( ) ) ;
}
2023-10-19 16:19:09 +02:00
GH . windows ( ) . popWindows ( 1 ) ;
}