2016-06-21 14:36:21 +06:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
*
2021-12-26 18:47:58 +01:00
* 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 .
2016-06-21 14:36:21 +06:00
*
* 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
2021-12-26 18:47:58 +01:00
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2016-06-21 14:36:21 +06:00
*
*/
# include "common/util.h"
# include "gui/widgets/scrollcontainer.h"
# include "gui/gui-manager.h"
# include "gui/ThemeEval.h"
namespace GUI {
2016-07-11 14:17:27 +06:00
ScrollContainerWidget : : ScrollContainerWidget ( GuiObject * boss , int x , int y , int w , int h , uint32 reflowCmd )
: Widget ( boss , x , y , w , h ) , CommandSender ( nullptr ) , _reflowCmd ( reflowCmd ) {
2016-06-21 14:36:21 +06:00
init ( ) ;
}
2019-12-28 10:43:58 +01:00
ScrollContainerWidget : : ScrollContainerWidget ( GuiObject * boss , const Common : : String & name , const Common : : String & dialogName , uint32 reflowCmd )
: Widget ( boss , name ) , CommandSender ( nullptr ) , _reflowCmd ( reflowCmd ) , _dialogName ( dialogName ) {
2016-06-21 14:36:21 +06:00
init ( ) ;
}
void ScrollContainerWidget : : init ( ) {
setFlags ( WIDGET_ENABLED ) ;
_type = kScrollContainerWidget ;
2019-12-28 10:43:58 +01:00
_backgroundType = ThemeEngine : : kWidgetBackgroundPlain ;
2016-06-21 14:36:21 +06:00
_verticalScroll = new ScrollBarWidget ( this , _w - 16 , 0 , 16 , _h ) ;
_verticalScroll - > setTarget ( this ) ;
_scrolledX = 0 ;
_scrolledY = 0 ;
_limitH = 140 ;
recalc ( ) ;
}
2018-10-11 05:52:02 +01:00
void ScrollContainerWidget : : handleMouseWheel ( int x , int y , int direction ) {
_verticalScroll - > handleMouseWheel ( x , y , direction ) ;
}
2016-06-21 14:36:21 +06:00
void ScrollContainerWidget : : recalc ( ) {
2016-06-22 18:44:47 +06:00
int scrollbarWidth = g_gui . xmlEval ( ) - > getVar ( " Globals.Scrollbar.Width " , 0 ) ;
2016-06-24 23:26:25 +06:00
_limitH = _h ;
2016-07-21 11:44:36 +06:00
2016-06-22 18:44:47 +06:00
//calculate virtual height
const int spacing = g_gui . xmlEval ( ) - > getVar ( " Global.Font.Height " , 16 ) ; //on the bottom
int min = spacing , max = 0 ;
Widget * ptr = _firstWidget ;
while ( ptr ) {
2016-07-11 14:17:27 +06:00
if ( ptr ! = _verticalScroll & & ptr - > isVisible ( ) ) {
2016-06-22 18:44:47 +06:00
int y = ptr - > getAbsY ( ) - getChildY ( ) ;
min = MIN ( min , y - spacing ) ;
max = MAX ( max , y + ptr - > getHeight ( ) + spacing ) ;
}
ptr = ptr - > next ( ) ;
}
2021-12-07 07:29:53 -06:00
int h = max - min ;
2016-06-22 18:44:47 +06:00
2016-07-11 14:30:46 +06:00
if ( h < = _limitH ) _scrolledY = 0 ;
2019-07-18 23:10:49 +07:00
if ( _scrolledY > h - _limitH ) _scrolledY = 0 ;
2016-07-11 14:30:46 +06:00
2016-06-22 18:44:47 +06:00
_verticalScroll - > _numEntries = h ;
2016-06-21 14:36:21 +06:00
_verticalScroll - > _currentPos = _scrolledY ;
_verticalScroll - > _entriesPerPage = _limitH ;
2018-07-23 23:36:37 +01:00
_verticalScroll - > _singleStep = kLineHeight ;
2019-07-31 00:42:35 +07:00
_verticalScroll - > setPos ( _w - scrollbarWidth , _scrolledY ) ;
_verticalScroll - > setSize ( scrollbarWidth , _limitH - 1 ) ;
2016-06-21 14:36:21 +06:00
}
2016-06-21 14:46:09 +06:00
ScrollContainerWidget : : ~ ScrollContainerWidget ( ) { }
2016-06-21 14:36:21 +06:00
int16 ScrollContainerWidget : : getChildX ( ) const {
2016-06-21 14:46:09 +06:00
return getAbsX ( ) - _scrolledX ;
2016-06-21 14:36:21 +06:00
}
int16 ScrollContainerWidget : : getChildY ( ) const {
2016-06-21 14:46:09 +06:00
return getAbsY ( ) - _scrolledY ;
2016-06-21 14:36:21 +06:00
}
uint16 ScrollContainerWidget : : getWidth ( ) const {
2016-06-23 17:50:38 +06:00
return _w - ( _verticalScroll - > isVisible ( ) ? _verticalScroll - > getWidth ( ) : 0 ) ;
2016-06-21 14:36:21 +06:00
}
uint16 ScrollContainerWidget : : getHeight ( ) const {
return _limitH ;
}
void ScrollContainerWidget : : handleCommand ( CommandSender * sender , uint32 cmd , uint32 data ) {
2016-07-02 13:26:05 +06:00
Widget : : handleCommand ( sender , cmd , data ) ;
2016-06-21 14:36:21 +06:00
switch ( cmd ) {
case kSetPositionCmd :
_scrolledY = _verticalScroll - > _currentPos ;
2016-06-22 15:21:35 +06:00
reflowLayout ( ) ;
2018-01-06 16:13:29 +01:00
g_gui . scheduleTopDialogRedraw ( ) ;
2016-06-21 14:36:21 +06:00
break ;
2019-10-03 06:03:46 +01:00
default :
break ;
2016-07-02 13:26:05 +06:00
}
2016-06-21 14:36:21 +06:00
}
void ScrollContainerWidget : : reflowLayout ( ) {
Widget : : reflowLayout ( ) ;
2016-06-23 12:52:38 +06:00
2019-12-28 10:43:58 +01:00
if ( ! _dialogName . empty ( ) ) {
g_gui . xmlEval ( ) - > reflowDialogLayout ( _dialogName , _firstWidget ) ;
}
2016-06-23 12:52:38 +06:00
//reflow layout of inner widgets
2016-06-22 15:21:35 +06:00
Widget * ptr = _firstWidget ;
2016-06-23 12:52:38 +06:00
while ( ptr ) {
ptr - > reflowLayout ( ) ;
ptr = ptr - > next ( ) ;
}
2016-07-11 14:17:27 +06:00
//hide and move widgets, if needed
sendCommand ( _reflowCmd , 0 ) ;
2016-07-21 11:44:36 +06:00
2016-06-23 12:52:38 +06:00
//recalculate height
recalc ( ) ;
2016-06-23 17:50:38 +06:00
_verticalScroll - > setVisible ( _verticalScroll - > _numEntries > _limitH ) ; //show when there is something to scroll
2016-07-11 14:30:46 +06:00
_verticalScroll - > recalc ( ) ;
2016-06-21 14:36:21 +06:00
}
void ScrollContainerWidget : : drawWidget ( ) {
2019-12-28 10:43:58 +01:00
g_gui . theme ( ) - > drawWidgetBackground ( Common : : Rect ( _x , _y , _x + _w , _y + getHeight ( ) ) , _backgroundType ) ;
2016-06-21 14:36:21 +06:00
}
2017-04-06 21:50:16 +01:00
bool ScrollContainerWidget : : containsWidget ( Widget * w ) const {
if ( w = = _verticalScroll | | _verticalScroll - > containsWidget ( w ) )
return true ;
return containsWidgetInChain ( _firstWidget , w ) ;
}
2016-06-21 14:36:21 +06:00
Widget * ScrollContainerWidget : : findWidget ( int x , int y ) {
2016-06-23 17:50:38 +06:00
if ( _verticalScroll - > isVisible ( ) & & x > = _w - _verticalScroll - > getWidth ( ) )
2016-06-22 18:44:47 +06:00
return _verticalScroll ;
2018-07-23 23:34:01 +01:00
Widget * w = Widget : : findWidgetInChain ( _firstWidget , x + _scrolledX , y + _scrolledY ) ;
if ( w )
return w ;
return this ;
2016-06-21 14:36:21 +06:00
}
2018-01-27 08:59:53 +01:00
Common : : Rect ScrollContainerWidget : : getClipRect ( ) const {
// Make sure the clipping rect contains the scrollbar so it is properly redrawn
2019-07-31 00:42:35 +07:00
return Common : : Rect ( getAbsX ( ) , getAbsY ( ) , getAbsX ( ) + _w , getAbsY ( ) + getHeight ( ) - 1 ) ; // this -1 is because of container border, which might not be present actually
2018-01-27 08:59:53 +01:00
}
2019-12-28 10:43:58 +01:00
void ScrollContainerWidget : : setBackgroundType ( ThemeEngine : : WidgetBackground backgroundType ) {
2018-11-14 20:16:34 +01:00
_backgroundType = backgroundType ;
}
2016-06-21 14:36:21 +06:00
} // End of namespace GUI