1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010-2020 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 // Copyright (C) 2015-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
8 // This program is free software: you can redistribute it and/or modify
9 // it under the terms of the GNU Affero General Public License as
10 // published by the Free Software Foundation, either version 3 of the
11 // License, or (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Affero General Public License for more details.
18 // You should have received a copy of the GNU Affero General Public License
19 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "nel/gui/widget_manager.h"
24 #include "nel/gui/action_handler.h"
25 #include "nel/gui/interface_group.h"
26 #include "nel/gui/view_renderer.h"
27 #include "nel/gui/ctrl_scroll.h"
28 #include "nel/misc/xml_auto_ptr.h"
29 #include "nel/gui/group_submenu_base.h"
30 #include "nel/gui/lua_ihm.h"
32 using namespace NLMISC
;
39 NLMISC_REGISTER_OBJECT(CViewBase
, CCtrlScroll
, std::string
, "scroll");
44 // ------------------------------------------------------------------------------------------------
45 CCtrlScroll::CCtrlScroll(const TCtorParam
¶m
)
46 : CCtrlScrollBase(param
)
52 _TrackSize
= _TrackSizeMin
= 8;
65 _LastTargetMaxHReal
= 0;
67 _LastTargetMaxWReal
= 0;
79 // ------------------------------------------------------------------------------------------------
80 void CCtrlScroll::runAH(const std::string
&name
, const std::string
¶ms
)
82 if (name
.empty()) return;
83 if (_CallingAH
) return; // avoid infinite loop
85 CAHManager::getInstance()->runActionHandler(name
, this, params
);
89 // ------------------------------------------------------------------------------------------------
90 CCtrlScroll::~CCtrlScroll()
94 ICDBNode::CTextId textId
;
95 _DBLink
.getNodePtr()->removeObserver(this, textId
);
99 std::string
CCtrlScroll::getProperty( const std::string
&name
) const
102 if( name
== "tx_bottomleft" )
104 return getTextureBottomOrLeft();
107 if( name
== "tx_middle" )
109 return getTextureMiddle();
112 if( name
== "tx_topright" )
114 return getTextureTopOrRight();
117 if( name
== "scale" )
119 return toString( _Scale
);
122 if( name
== "vertical" )
124 return toString( _Vertical
);
127 if( name
== "align" )
150 return toString( _Min
);
155 return toString( _Max
);
158 if( name
== "value" )
161 return _DBLink
.getNodePtr()->getFullName();
163 return toString( _Value
);
166 if( name
== "tracksize" )
168 return toString( _TrackSize
);
171 if( name
== "onscroll" )
176 if( name
== "params" )
178 return _AHOnScrollParams
;
181 if( name
== "onscrollend" )
183 return _AHOnScrollEnd
;
186 if( name
== "end_params" )
188 return _AHOnScrollEndParams
;
191 if( name
== "onscrollcancel" )
193 return _AHOnScrollCancel
;
196 if( name
== "cancel_params" )
198 return _AHOnScrollCancelParams
;
201 if( name
== "target" )
203 if( _Target
!= NULL
)
204 return _Target
->getId();
209 if( name
== "target_stepx" )
211 return toString( _TargetStepX
);
214 if( name
== "target_stepy" )
216 return toString( _TargetStepY
);
219 if( name
== "step_value" )
221 return toString( _StepValue
);
224 if( name
== "cancelable" )
226 return toString( _Cancelable
);
229 if( name
== "keyboard" )
231 return toString( _Keyboard
);
234 if( name
== "frozen" )
236 return toString( _Frozen
);
239 return CCtrlBase::getProperty( name
);
243 void CCtrlScroll::setProperty( const std::string
&name
, const std::string
&value
)
245 if( name
== "tx_bottomleft" )
247 setTextureBottomOrLeft( value
);
251 if( name
== "tx_middle" )
253 setTextureMiddle( value
);
257 if( name
== "tx_topright" )
259 setTextureTopOrRight( value
);
266 if (fromString( value
, b
) )
271 if( name
== "vertical" )
274 if( fromString( value
, b
) )
279 if( name
== "align" )
299 if( fromString( value
, i
) )
307 if( fromString( value
, i
) )
312 if( name
== "value" )
315 if( fromString( value
, i
) )
323 _DBLink
.link( value
.c_str() );
324 ICDBNode::CTextId dummy
;
325 _DBLink
.getNodePtr()->addObserver( this, dummy
);
330 if( name
== "tracksize" )
333 if( fromString( value
, i
) )
338 if( name
== "onscroll" )
344 if( name
== "params" )
346 _AHOnScrollParams
= value
;
350 if( name
== "onscrollend" )
352 _AHOnScrollEnd
= value
;
356 if( name
== "end_params" )
358 _AHOnScrollEndParams
= value
;
362 if( name
== "onscrollcancel" )
364 _AHOnScrollCancel
= value
;
368 if( name
== "cancel_params" )
370 _AHOnScrollCancelParams
= value
;
374 if( name
== "target" )
376 _Target
= dynamic_cast< CInterfaceGroup
* >(
377 CWidgetManager::getInstance()->getElementFromId( value
)
382 if( name
== "target_stepx" )
385 if( fromString( value
, i
) )
390 if( name
== "target_stepy" )
393 if( fromString( value
, i
) )
398 if( name
== "step_value" )
401 if( fromString( value
, i
) )
406 if( name
== "cancelable" )
409 if( fromString( value
, b
) )
414 if( name
== "keyboard" )
417 if( fromString( value
, b
) )
422 if( name
== "frozen" )
425 if( fromString( value
, b
) )
430 CCtrlBase::setProperty( name
, value
);
433 xmlNodePtr
CCtrlScroll::serialize( xmlNodePtr parentNode
, const char *type
) const
435 xmlNodePtr node
= CCtrlBase::serialize( parentNode
, type
);
439 xmlSetProp( node
, BAD_CAST
"type", BAD_CAST
"scroll" );
440 xmlSetProp( node
, BAD_CAST
"tx_bottomleft", BAD_CAST
getTextureBottomOrLeft().c_str() );
441 xmlSetProp( node
, BAD_CAST
"tx_middle", BAD_CAST
getTextureMiddle().c_str() );
442 xmlSetProp( node
, BAD_CAST
"tx_topright", BAD_CAST
getTextureTopOrRight().c_str() );
443 xmlSetProp( node
, BAD_CAST
"scale", BAD_CAST
toString( _Scale
).c_str() );
444 xmlSetProp( node
, BAD_CAST
"vertical", BAD_CAST
toString( _Vertical
).c_str() );
466 xmlSetProp( node
, BAD_CAST
"align", BAD_CAST align
.c_str() );
468 xmlSetProp( node
, BAD_CAST
"min", BAD_CAST
toString( _Min
).c_str() );
469 xmlSetProp( node
, BAD_CAST
"max", BAD_CAST
toString( _Max
).c_str() );
472 xmlSetProp( node
, BAD_CAST
"value", BAD_CAST _DBLink
.getNodePtr()->getFullName().c_str() );
474 xmlSetProp( node
, BAD_CAST
"tracksize", BAD_CAST
toString( _TrackSize
).c_str() );
475 xmlSetProp( node
, BAD_CAST
"onscroll", BAD_CAST _AHOnScroll
.c_str() );
476 xmlSetProp( node
, BAD_CAST
"params", BAD_CAST _AHOnScrollParams
.c_str() );
477 xmlSetProp( node
, BAD_CAST
"onscrollend", BAD_CAST _AHOnScrollEnd
.c_str() );
478 xmlSetProp( node
, BAD_CAST
"end_params", BAD_CAST _AHOnScrollEndParams
.c_str() );
479 xmlSetProp( node
, BAD_CAST
"onscrollcancel", BAD_CAST _AHOnScrollCancel
.c_str() );
480 xmlSetProp( node
, BAD_CAST
"cancel_params", BAD_CAST _AHOnScrollCancelParams
.c_str() );
482 if( _Target
!= NULL
)
483 xmlSetProp( node
, BAD_CAST
"target", BAD_CAST _Target
->getId().c_str() );
485 xmlSetProp( node
, BAD_CAST
"target", BAD_CAST
"" );
487 xmlSetProp( node
, BAD_CAST
"target_stepx", BAD_CAST
toString( _TargetStepX
).c_str() );
488 xmlSetProp( node
, BAD_CAST
"target_stepy", BAD_CAST
toString( _TargetStepY
).c_str() );
489 xmlSetProp( node
, BAD_CAST
"step_value", BAD_CAST
toString( _StepValue
).c_str() );
490 xmlSetProp( node
, BAD_CAST
"cancelable", BAD_CAST
toString( _Cancelable
).c_str() );
491 xmlSetProp( node
, BAD_CAST
"keyboard", BAD_CAST
toString( _Keyboard
).c_str() );
492 xmlSetProp( node
, BAD_CAST
"frozen", BAD_CAST
toString( _Frozen
).c_str() );
497 // ------------------------------------------------------------------------------------------------
498 bool CCtrlScroll::parse(xmlNodePtr node
, CInterfaceGroup
* parentGroup
)
500 if (!CCtrlBase::parse(node
, parentGroup
))
505 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"tx_bottomleft" );
506 if(prop
) setTextureBottomOrLeft(string((const char*)prop
));
507 else setTextureBottomOrLeft ("w_scroll_l0_b.tga");
509 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"tx_middle" );
510 if(prop
) setTextureMiddle(string((const char*)prop
));
511 else setTextureMiddle ("w_scroll_l0_m.tga");
513 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"tx_topright" );
514 if(prop
) setTextureTopOrRight(string((const char*)prop
));
515 else setTextureTopOrRight ("w_scroll_l0_t.tga");
517 // Override texture size (w for vertical, h for horizontal)
518 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"scale" );
519 if (prop
) _Scale
= convertBool((const char*)prop
);
522 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"vertical" );
523 if (prop
) _Vertical
= convertBool((const char*)prop
);
525 prop
= (char*) xmlGetProp (node
, (xmlChar
*)"align");
529 if (stricmp(prop
, "T") == 0) _Aligned
= 0;
530 else if (stricmp(prop
, "B") == 0) _Aligned
= 1;
531 else if (stricmp(prop
, "L") == 0) _Aligned
= 2;
532 else if (stricmp(prop
, "R") == 0) _Aligned
= 3;
535 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"min" );
536 if (prop
) fromString((const char*)prop
, _Min
);
538 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"max" );
539 if (prop
) fromString((const char*)prop
, _Max
);
541 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"value" );
544 if ( isdigit(*prop
) || *prop
=='-')
547 fromString((const char*)prop
, _Value
);
553 ICDBNode::CTextId textId
;
554 _DBLink
.getNodePtr()->addObserver(this, textId
);
559 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"tracksize" );
560 if (prop
) fromString((const char*)prop
, _TrackSize
);
562 // Read Action handlers
563 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"onscroll" );
564 if (prop
) _AHOnScroll
= NLMISC::toLowerAscii(prop
.str());
565 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"params" );
566 if (prop
) _AHOnScrollParams
= string((const char*)prop
);
568 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"onscrollend" );
569 if (prop
) _AHOnScrollEnd
= NLMISC::toLowerAscii(prop
.str());
570 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"end_params" );
571 if (prop
) _AHOnScrollEndParams
= string((const char*)prop
);
573 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"onscrollcancel" );
574 if (prop
) _AHOnScrollCancel
= NLMISC::toLowerAscii(prop
.str());
575 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"cancel_params" );
576 if (prop
) _AHOnScrollCancelParams
= string((const char*)prop
);
580 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"target" );
583 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(prop
.str()));
585 group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(this->getId(), prop
.str()));
593 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"target_stepx" );
594 if(prop
) fromString((const char*)prop
, _TargetStepX
);
595 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"target_stepy" );
596 if(prop
) fromString((const char*)prop
, _TargetStepY
);
597 _TargetStepX
= max((sint32
)1, _TargetStepX
);
598 _TargetStepY
= max((sint32
)1, _TargetStepY
);
601 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"step_value" );
602 if(prop
) fromString((const char*)prop
, _StepValue
);
604 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"cancelable" );
605 if (prop
) _Cancelable
= convertBool(prop
);
607 prop
= (char*) xmlGetProp( node
, (xmlChar
*)"keyboard" );
608 if (prop
) _Keyboard
= convertBool(prop
);
610 prop
= (char*) xmlGetProp (node
, (xmlChar
*)"frozen");
613 _Frozen
= convertBool(prop
);
619 // ------------------------------------------------------------------------------------------------
621 int CCtrlScroll::luaSetTarget(CLuaState
&ls
)
623 const char *funcName
= "setTarget";
624 CLuaIHM::checkArgCount(ls
, funcName
, 1);
625 CLuaIHM::checkArgType(ls
, funcName
, 1, LUA_TSTRING
);
626 std::string targetId
= ls
.toString(1);
628 CInterfaceGroup
*group
= dynamic_cast<CInterfaceGroup
*>(CWidgetManager::getInstance()->getElementFromId(targetId
));
637 void CCtrlScroll::updateCoords()
641 // update only if visible
642 if (_Target
->getActive())
644 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
646 rVR
.getTextureSizeFromId (_TxIdB
, w
, h
);
651 _H
= _Target
->getMaxHReal();
655 _W
= _Target
->getMaxWReal();
659 CCtrlBase::updateCoords ();
662 if(_Target
->getHReal()!=_LastTargetHReal
|| _Target
->getMaxHReal()!=_LastTargetMaxHReal
||
663 _Target
->getOfsY() != _LastTargetOfsY
666 _LastTargetHReal
= _Target
->getHReal();
667 _LastTargetMaxHReal
= _Target
->getMaxHReal();
668 _LastTargetOfsY
= _Target
->getOfsY();
670 // Activate only if needed
671 setActive(_Target
->getHReal() > _Target
->getMaxHReal());
672 CCtrlBase::updateCoords();
674 // Calculate size of the track button
675 if ((_Target
->getHReal() <= _Target
->getMaxHReal()) || (_Target
->getHReal() == 0))
677 _TrackSize
= _Target
->getMaxHReal();
681 float factor
= (float)_Target
->getMaxHReal() / (float)_Target
->getHReal();
682 factor
= _TrackSizeMin
+ factor
* (this->getHReal() - _TrackSizeMin
);
683 _TrackSize
= (sint32
)factor
;
685 // Calculate pos of the track button
686 if (_Target
->getHReal() <= _Target
->getMaxHReal())
688 if (_Aligned
== 1) // BOTTOM
691 _TrackPos
= getHReal()-_TrackSize
;
695 if (_Aligned
== 1) // BOTTOM
697 float factor
= ((float)_Target
->getHReal() - (float)_Target
->getMaxHReal());
698 factor
= -(float)_Target
->getOfsY() / factor
;
699 if (factor
< 0.0f
) factor
= 0.0f
;
700 if (factor
> 1.0f
) factor
= 1.0f
;
701 _TrackPos
= factor
* (getHReal()-_TrackSize
);
705 float factor
= ((float)_Target
->getHReal() - (float)_Target
->getMaxHReal());
706 factor
= (float)_Target
->getOfsY() / factor
;
707 if (factor
< 0.0f
) factor
= 0.0f
;
708 if (factor
> 1.0f
) factor
= 1.0f
;
709 sint32 hreal
= getHReal();
710 _TrackPos
= (1.0f
-factor
) * (hreal
- _TrackSize
);
714 // invalidate coords.
715 computeTargetOfsFromPos();
718 else // Horizontal Tracker
720 if(_Target
->getWReal()!=_LastTargetWReal
|| _Target
->getMaxWReal()!=_LastTargetMaxWReal
||
721 _Target
->getOfsX() != _LastTargetOfsX
)
723 _LastTargetWReal
= _Target
->getWReal();
724 _LastTargetMaxWReal
= _Target
->getMaxWReal();
725 _LastTargetOfsX
= _Target
->getOfsX();
727 // Activate only if needed
728 setActive(_Target
->getWReal() > _Target
->getMaxWReal());
729 CCtrlBase::updateCoords();
731 // Calculate size of the track button
732 if ((_Target
->getWReal() <= _Target
->getMaxWReal()) || (_Target
->getWReal() == 0))
734 _TrackSize
= _Target
->getMaxWReal();
738 float factor
= (float)_Target
->getMaxWReal() / (float)_Target
->getWReal();
739 factor
= _TrackSizeMin
+ factor
* (this->getWReal() - _TrackSizeMin
);
740 _TrackSize
= (sint32
)factor
;
742 // Calculate pos of the track button
743 if (_Target
->getWReal() <= _Target
->getMaxWReal())
745 if (_Aligned
== 2) // LEFT
748 _TrackPos
= getWReal()-_TrackSize
;
752 if (_Aligned
== 2) // LEFT
754 float factor
= ((float)_Target
->getWReal() - (float)_Target
->getMaxWReal());
755 factor
= -(float)_Target
->getOfsX() / factor
;
756 if (factor
< 0.0f
) factor
= 0.0f
;
757 if (factor
> 1.0f
) factor
= 1.0f
;
758 _TrackPos
= factor
* (getWReal()-_TrackSize
);
762 float factor
= ((float)_Target
->getWReal() - (float)_Target
->getMaxWReal());
763 factor
= (float)_Target
->getOfsX() / factor
;
764 if (factor
< 0.0f
) factor
= 0.0f
;
765 if (factor
> 1.0f
) factor
= 1.0f
;
766 sint32 hreal
= getWReal();
767 _TrackPos
= (1.0f
-factor
) * (hreal
- _TrackSize
);
771 // invalidate coords.
772 computeTargetOfsFromPos();
780 _LastTargetMaxHReal
= 0;
782 _LastTargetMaxWReal
= 0;
790 CCtrlBase::updateCoords ();
792 _Value
= _DBLink
.getSInt32();
796 if (_Aligned
== 1) // BOTTOM
797 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
799 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
800 factor
*= (this->getHReal() - _TrackSize
);
802 _TrackDispPos
= (sint32
)factor
;
807 if (_Aligned
== 2) // LEFT
808 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
810 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
811 factor
*= (this->getWReal() - _TrackSize
);
813 _TrackDispPos
= (sint32
)factor
;
816 CCtrlBase::updateCoords ();
819 // ------------------------------------------------------------------------------------------------
820 void CCtrlScroll::draw()
822 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
823 CRGBA col
= CWidgetManager::getInstance()->getGlobalColorForContent();
829 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackPos
, _WReal
, 4, 0, false, _TxIdB
, col
);
831 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackPos
+4, _WReal
, _TrackSize
-8, 0, false, _TxIdM
, col
);
833 rVR
.drawRotFlipBitmapTiled (_RenderLayer
, _XReal
, _YReal
+_TrackPos
+4, _WReal
, _TrackSize
-8, 0, false, _TxIdM
, _TileM
-1, col
);
834 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackPos
+_TrackSize
-4, _WReal
, 4, 0, false, _TxIdT
, col
);
838 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackPos
, _YReal
, 4, _HReal
, 0, false, _TxIdB
, col
);
840 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackPos
+4, _YReal
, _TrackSize
-8, _HReal
, 0, false, _TxIdM
, col
);
842 rVR
.drawRotFlipBitmapTiled (_RenderLayer
, _XReal
+_TrackPos
+4, _YReal
, _TrackSize
-8, _HReal
, 0, false, _TxIdM
, _TileM
-1, col
);
843 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackPos
+_TrackSize
-4, _YReal
, 4, _HReal
, 0, false, _TxIdT
, col
);
850 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackDispPos
, _WReal
, 4, 0, false, _TxIdB
, col
);
852 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackDispPos
+4, _WReal
, _TrackSize
-8, 0, false, _TxIdM
, col
);
854 rVR
.drawRotFlipBitmapTiled (_RenderLayer
, _XReal
, _YReal
+_TrackDispPos
+4, _WReal
, _TrackSize
-8, 0, false, _TxIdM
, _TileM
-1, col
);
855 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
, _YReal
+_TrackDispPos
+_TrackSize
-4, _WReal
, 4, 0, false, _TxIdT
, col
);
859 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackDispPos
, _YReal
, 4, _HReal
, 0, false, _TxIdB
, col
);
861 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackDispPos
+4, _YReal
, _TrackSize
-8, _HReal
, 0, false, _TxIdM
, col
);
863 rVR
.drawRotFlipBitmapTiled (_RenderLayer
, _XReal
+_TrackDispPos
+4, _YReal
, _TrackSize
-8, _HReal
, 0, false, _TxIdM
, _TileM
-1, col
);
864 rVR
.drawRotFlipBitmap (_RenderLayer
, _XReal
+_TrackDispPos
+_TrackSize
-4, _YReal
, 4, _HReal
, 0, false, _TxIdT
, col
);
869 // ------------------------------------------------------------------------------------------------
870 bool CCtrlScroll::handleEvent (const NLGUI::CEventDescriptor
&event
)
872 if (CCtrlBase::handleEvent(event
)) return true;
873 if (!_Active
|| _Frozen
)
876 if (event
.getType() == NLGUI::CEventDescriptor::mouse
)
878 const NLGUI::CEventDescriptorMouse
&eventDesc
= (const NLGUI::CEventDescriptorMouse
&)event
;
879 if ((CWidgetManager::getInstance()->getCapturePointerLeft() != this) &&
880 (!((eventDesc
.getX() >= _XReal
) &&
881 (eventDesc
.getX() < (_XReal
+ _WReal
))&&
882 (eventDesc
.getY() > _YReal
) &&
883 (eventDesc
.getY() <= (_YReal
+ _HReal
)))))
886 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown
)
889 _InitialValue
= getValue();
891 _TrackPos
= _TrackDispPos
;
892 _MouseDownOffsetX
= eventDesc
.getX() - (getXReal() + (_Vertical
? 0 : _TrackPos
));
893 _MouseDownOffsetY
= eventDesc
.getY() - (getYReal() + (_Vertical
? _TrackPos
: 0));
895 // if target is a menu, hidde its sub menus
896 if(_Target
&& _Target
->getParent())
898 CGroupSubMenuBase
*menu
= dynamic_cast<CGroupSubMenuBase
*>(_Target
->getParent());
900 menu
->hideSubMenus();
904 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup
)
907 runAH(_AHOnScrollEnd
, _AHOnScrollEndParams
.empty() ? _AHOnScrollParams
: _AHOnScrollEndParams
); // backward compatibility
910 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown
&& _MouseDown
&& _Cancelable
)
913 setValue(_InitialValue
);
914 runAH(_AHOnScrollCancel
, _AHOnScrollCancelParams
); // backward compatibility
917 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove
)
921 sint32 dx
= eventDesc
.getX() - (getXReal() + (_Vertical
? 0 : _TrackPos
) + _MouseDownOffsetX
);
922 sint32 dy
= eventDesc
.getY() - (getYReal() + (_Vertical
? _TrackPos
: 0 ) + _MouseDownOffsetY
);
923 if (dx
!= 0) moveTrackX (dx
);
924 if (dy
!= 0) moveTrackY (dy
);
928 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel
&& _Vertical
)
930 moveTargetY (-(eventDesc
.getWheel() * 12));
934 else if (event
.getType() == NLGUI::CEventDescriptor::key
)
936 const NLGUI::CEventDescriptorKey
&eventDesc
= (const NLGUI::CEventDescriptorKey
&)event
;
938 if (eventDesc
.getKeyEventType() == NLGUI::CEventDescriptorKey::keydown
)
944 if (eventDesc
.getKey() == KeyNEXT
) i
++;
945 else if (eventDesc
.getKey() == KeyPRIOR
) i
--;
950 moveTrackY(-(i
* _TargetStepY
));
952 moveTrackX(-(i
* _TargetStepX
));
961 // ------------------------------------------------------------------------------------------------
962 void CCtrlScroll::setTarget (CInterfaceGroup
*pIG
)
968 if (_Target
->getPosRef()&Hotspot_Tx
)
973 if (_Target
->getPosRef()&Hotspot_Tx
)
980 if (_Target
->getPosRef()&Hotspot_xL
)
985 if (_Target
->getPosRef()&Hotspot_xL
)
991 // ------------------------------------------------------------------------------------------------
992 sint32
CCtrlScroll::moveTrackX (sint32 dx
)
996 if ((getWReal()-_TrackSize
) <= 0)
1000 float tpos
= _TrackPos
;
1001 sint32 tsize
= _TrackSize
;
1003 // Limit the scroller to the defined area
1004 newtpos
= tpos
+ dx
;
1005 if (newtpos
< 0) newtpos
= 0;
1006 if (newtpos
> (getWReal()-tsize
)) newtpos
= (getWReal()-tsize
);
1007 dx
= newtpos
- tpos
;
1011 _TrackPos
= newtpos
;
1013 computeTargetOfsFromPos();
1015 else // This is a number scroller
1017 float factor
= (float)(_Max
- _Min
);
1019 if (_Aligned
== 2) // LEFT
1020 factor
= -factor
* newtpos
/ (float)(getWReal()-tsize
) - _Min
;
1022 factor
= factor
* (1.0f
-(newtpos
/ (float)(getWReal()-tsize
))) + _Min
;
1024 _TrackPos
= newtpos
;
1026 if (_Aligned
== 2) // LEFT
1027 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1029 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1031 // step and clamp value
1032 normalizeValue(_Value
);
1036 if (_Aligned
== 2) // LEFT
1037 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
1039 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
1040 factor
*= (this->getWReal() - _TrackSize
);
1042 _TrackDispPos
= (sint32
)factor
;
1047 _ObserverOn
= false;
1048 _DBLink
.setSInt32 (_Value
);
1053 // Launch the scroller event if any
1054 runAH(_AHOnScroll
, _AHOnScrollParams
);
1059 // ------------------------------------------------------------------------------------------------
1060 sint32
CCtrlScroll::moveTrackY (sint32 dy
)
1064 if ((getHReal()-_TrackSize
) <= 0)
1068 float tpos
= _TrackPos
;
1069 sint32 tsize
= _TrackSize
;
1071 // Limit the scroller to the defined area
1072 newtpos
= tpos
+ dy
;
1073 if (newtpos
< 0) newtpos
= 0;
1074 if (newtpos
> (getHReal()-tsize
)) newtpos
= (getHReal()-tsize
);
1075 dy
= newtpos
- tpos
;
1079 _TrackPos
= newtpos
;
1081 computeTargetOfsFromPos();
1083 else // This is a number scroller
1085 float factor
= (float)(_Max
- _Min
);
1087 if (_Aligned
== 1) // BOTTOM
1088 factor
= -factor
* newtpos
/ (float)(getHReal()-tsize
) - _Min
;
1090 factor
= factor
* (1.0f
-(newtpos
/ (float)(getHReal()-tsize
))) + _Min
;
1092 _TrackPos
= newtpos
;
1094 if (_Aligned
== 1) // BOTTOM
1095 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1097 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1099 // step and clamp value
1100 normalizeValue(_Value
);
1104 if (_Aligned
== 1) // BOTTOM
1105 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
1107 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
1108 factor
*= (this->getHReal() - _TrackSize
);
1110 _TrackDispPos
= (sint32
)factor
;
1115 _ObserverOn
= false;
1116 _DBLink
.setSInt32 (_Value
);
1121 // Launch the scroller event if any
1122 runAH(_AHOnScroll
, _AHOnScrollParams
);
1127 // ------------------------------------------------------------------------------------------------
1128 void CCtrlScroll::setTextureBottomOrLeft (const std::string
&txName
)
1130 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1131 _TxIdB
= rVR
.getTextureIdFromName(txName
);
1134 // ------------------------------------------------------------------------------------------------
1135 void CCtrlScroll::setTextureMiddle (const std::string
&txName
)
1137 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1138 _TxIdM
= rVR
.getTextureIdFromName(txName
);
1141 // ------------------------------------------------------------------------------------------------
1142 void CCtrlScroll::setTextureTopOrRight (const std::string
&txName
)
1144 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1145 _TxIdT
= rVR
.getTextureIdFromName(txName
);
1148 std::string
CCtrlScroll::getTextureBottomOrLeft() const
1150 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdB
);
1153 std::string
CCtrlScroll::getTextureMiddle() const
1155 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdM
);
1158 std::string
CCtrlScroll::getTextureTopOrRight() const
1160 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdT
);
1163 // ------------------------------------------------------------------------------------------------
1164 void CCtrlScroll::setValue(sint32 value
)
1166 normalizeValue(value
);
1170 _ObserverOn
= false;
1171 _DBLink
.setSInt32(value
);
1181 // ------------------------------------------------------------------------------------------------
1182 void CCtrlScroll::setTrackPos(sint32 pos
)
1186 moveTrackY(pos
- _TrackPos
);
1190 moveTrackX(pos
- _TrackPos
);
1195 // ------------------------------------------------------------------------------------------------
1196 void CCtrlScroll::computeTargetOfsFromPos()
1200 float factor
= ((float)_Target
->getHReal() - (float)_Target
->getMaxHReal());
1202 if (_Aligned
== 1) // BOTTOM
1203 factor
= -factor
* _TrackPos
/ favoid0((float)(getHReal()-_TrackSize
));
1205 factor
= factor
* (1.0f
-(_TrackPos
/ favoid0((float)(getHReal()-_TrackSize
))));
1207 // Compute Steped target
1208 sint32 nexOfsY
= (sint32
) floorf(0.5+(_Inverted
? factor
: -factor
));
1210 nexOfsY
= ((nexOfsY
+_TargetStepY
/2)/_TargetStepY
) * _TargetStepY
;
1211 _Target
->setOfsY (nexOfsY
);
1212 _LastTargetOfsY
= nexOfsY
;
1214 // invalidate only XReal/YReal, doing only 1 pass
1215 _Target
->invalidateCoords(1);
1219 float factor
= ((float)_Target
->getWReal() - (float)_Target
->getMaxWReal());
1221 if (_Aligned
== 2) // LEFT
1222 factor
= -factor
* _TrackPos
/ favoid0((float)(getWReal()-_TrackSize
));
1224 factor
= factor
* (1.0f
-(_TrackPos
/ favoid0((float)(getWReal()-_TrackSize
))));
1226 // Compute Steped target
1227 sint32 nexOfsX
= (sint32
) floorf(0.5+(_Inverted
? factor
: -factor
));
1229 nexOfsX
= ((nexOfsX
+_TargetStepX
/2)/_TargetStepX
) * _TargetStepX
;
1230 _Target
->setOfsX (nexOfsX
);
1231 _LastTargetOfsX
= nexOfsX
;
1233 // invalidate only XReal/YReal, doing only 1 pass
1234 _Target
->invalidateCoords(1);
1238 // ------------------------------------------------------------------------------------------------
1239 void CCtrlScroll::update(ICDBNode
* /* node */)
1241 if (!_ObserverOn
) return;
1242 _Value
= _DBLink
.getSInt32();
1243 // the value in the db changed
1244 invalidateCoords(1);
1245 if (_Target
) _Target
->invalidateCoords(1);
1249 // ***************************************************************************
1250 void CCtrlScroll::moveTargetX (sint32 dx
)
1254 sint32 maxWReal
= _Target
->getMaxWReal();
1255 sint32 wReal
= _Target
->getWReal();
1256 if(wReal
<= maxWReal
)
1260 // compute the new ofsX.
1261 sint32 ofsX
= _Target
->getOfsX();
1263 clamp(ofsX
, 0, wReal
-maxWReal
);
1264 _Target
->setOfsX(ofsX
);
1266 // compute new trackPos.
1267 if (_Aligned
== 2) // LEFT
1269 float factor
= (float)(wReal
-maxWReal
);
1270 factor
= -(float)ofsX
/ factor
;
1271 clamp(factor
, 0.f
, 1.f
);
1272 _TrackPos
= factor
* (getWReal()-_TrackSize
);
1276 float factor
= (float)(wReal
-maxWReal
);
1277 factor
= (float)ofsX
/ factor
;
1278 clamp(factor
, 0.f
, 1.f
);
1279 _TrackPos
= (1.0f
-factor
) * (getWReal() - _TrackSize
);
1282 // invalidate only position. 1 pass is sufficient
1283 invalidateCoords(1);
1286 // ***************************************************************************
1287 void CCtrlScroll::moveTargetY (sint32 dy
)
1291 sint32 maxHReal
= _Target
->getMaxHReal();
1292 sint32 hReal
= _Target
->getHReal();
1293 if(hReal
<= maxHReal
)
1296 if (_TargetStepY
> 1)
1298 sint sign
= (0 < dy
) - (dy
< 0);
1299 dy
= sign
* max(1, (dy
/ _TargetStepY
)) * _TargetStepY
;
1302 // compute the new ofsY.
1303 sint32 ofsY
= _Target
->getOfsY();
1306 // compute new trackPos.
1307 if (_Aligned
== 1) // BOTTOM
1309 clamp(ofsY
, maxHReal
- hReal
, 0);
1310 _Target
->setOfsY(ofsY
);
1311 float factor
= (float)(hReal
-maxHReal
);
1312 factor
= -(float)ofsY
/ factor
;
1313 clamp(factor
, 0.f
, 1.f
);
1314 _TrackPos
= factor
* (getHReal()-_TrackSize
);
1318 clamp(ofsY
, 0, hReal
-maxHReal
);
1319 _Target
->setOfsY(ofsY
);
1320 float factor
= (float)(hReal
-maxHReal
);
1321 factor
= (float)ofsY
/ factor
;
1322 clamp(factor
, 0.f
, 1.f
);
1323 _TrackPos
= (1.0f
-factor
) * (getHReal() - _TrackSize
);
1326 // invalidate only position. 1 pass is sufficient
1327 invalidateCoords(1);
1330 // ***************************************************************************
1331 void CCtrlScroll::normalizeValue(sint32
&value
)
1334 if(_StepValue
==0 || _StepValue
==1)
1336 // if interval is null, force min!
1343 // get range of possible position
1344 // sint32 size= _Max - _Min;
1347 sint32 val
= (value
+ (_StepValue
/2) -_Min
) / _StepValue
;
1348 val
= _Min
+ val
* _StepValue
;
1349 clamp(val
, _Min
, _Max
);
1353 // ***************************************************************************
1354 void CCtrlScroll::setFrozen (bool state
)
1364 // ------------------------------------------------------------------------------------------------
1365 int CCtrlScroll::luaEnsureVisible(CLuaState
&ls
)
1367 const char *funcName
= "ensureVisible";
1368 CLuaIHM::checkArgCount(ls
, funcName
, 3);
1369 CLuaIHM::checkArgTypeUIElement(ls
, funcName
, 1);
1370 CLuaIHM::checkArgType(ls
, funcName
, 2, LUA_TSTRING
);
1371 CLuaIHM::checkArgType(ls
, funcName
, 3, LUA_TSTRING
);
1373 std::string hsStr
[] = { ls
.toString(2), ls
.toString(3) };
1375 for (uint hsIndex
= 0; hsIndex
< 2; ++ hsIndex
)
1379 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "T") == 0)
1381 hs
[hsIndex
] = Hotspot_Tx
;
1384 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "M") == 0)
1386 hs
[hsIndex
] = Hotspot_Mx
;
1389 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "B") == 0)
1391 hs
[hsIndex
] = Hotspot_Bx
;
1395 hs
[hsIndex
] = Hotspot_Bx
;
1396 CLuaIHM::fails(ls
, "%s : couldn't parse hotspot for vertical scrollbar", funcName
);
1401 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "L") == 0)
1403 hs
[hsIndex
] = Hotspot_xL
;
1406 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "M") == 0)
1408 hs
[hsIndex
] = Hotspot_xM
;
1411 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "R") == 0)
1413 hs
[hsIndex
] = Hotspot_xR
;
1417 hs
[hsIndex
] = Hotspot_xL
;
1418 CLuaIHM::fails(ls
, "%s : couldn't parse hotspot for horizontal scrollbar", funcName
);
1422 ensureVisible(CLuaIHM::getUIOnStack(ls
, 1), hs
[0], hs
[1]);
1427 // ------------------------------------------------------------------------------------------------
1428 void CCtrlScroll::ensureVisible(CInterfaceElement
*childElement
, THotSpot childHotSpot
, THotSpot parentHotSpot
)
1430 if (!_Target
) return; // not connected to a target yet
1431 if (!childElement
) return;
1432 // compute corners of interest for enclosed element & enclosing group
1433 sint32 childX
, childY
;
1434 childElement
->getCorner(childX
, childY
, childHotSpot
);
1437 sint32 maxHReal
= _Target
->getMaxHReal();
1438 sint32 hReal
= _Target
->getHReal();
1439 if(hReal
> maxHReal
)
1442 switch (parentHotSpot
)
1445 enclosingDY
= maxHReal
;
1448 enclosingDY
= maxHReal
/ 2;
1460 sint32 offsetY
= (_Target
->getYReal() + _Target
->getHReal() - childY
) - enclosingDY
;
1461 NLMISC::clamp(offsetY
, 0, hReal
- maxHReal
);
1462 _Target
->setOfsY(offsetY
);
1463 _Target
->invalidateCoords();
1465 else if (_Aligned
== 1)
1467 // Bottom aligned case
1468 sint32 offsetY
= (maxHReal
- enclosingDY
) - (childY
- _Target
->getYReal());
1469 NLMISC::clamp(offsetY
, maxHReal
- hReal
, 0);
1470 _Target
->setOfsY(offsetY
);
1471 _Target
->invalidateCoords();
1474 // else, ... fully visible (not occluded by parent group)
1478 sint32 maxWReal
= _Target
->getMaxWReal();
1479 sint32 wReal
= _Target
->getWReal();
1480 if(wReal
> maxWReal
)
1483 switch (parentHotSpot
)
1486 enclosingDX
= maxWReal
;
1489 enclosingDX
= maxWReal
/ 2;
1500 // right aligned case
1501 sint32 offsetX
= (_Target
->getXReal() + _Target
->getWReal() - childX
) - enclosingDX
;
1502 NLMISC::clamp(offsetX
, 0, wReal
- maxWReal
);
1503 _Target
->setOfsX(offsetX
);
1504 _Target
->invalidateCoords();
1506 else if (_Aligned
== 2)
1508 // Left aligned case
1509 sint32 offsetX
= (maxWReal
- enclosingDX
) - (childX
- _Target
->getXReal());
1510 NLMISC::clamp(offsetX
, maxWReal
- wReal
, 0);
1511 _Target
->setOfsX(offsetX
);
1512 _Target
->invalidateCoords();
1515 // else, ... fully visible (not occluded by parent group)