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
)
875 if (event
.getType() == NLGUI::CEventDescriptor::mouse
)
877 const NLGUI::CEventDescriptorMouse
&eventDesc
= (const NLGUI::CEventDescriptorMouse
&)event
;
878 if ((CWidgetManager::getInstance()->getCapturePointerLeft() != this) &&
879 (!((eventDesc
.getX() >= _XReal
) &&
880 (eventDesc
.getX() < (_XReal
+ _WReal
))&&
881 (eventDesc
.getY() > _YReal
) &&
882 (eventDesc
.getY() <= (_YReal
+ _HReal
)))))
885 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftdown
)
888 _InitialValue
= getValue();
890 _TrackPos
= _TrackDispPos
;
891 _MouseDownOffsetX
= eventDesc
.getX() - (getXReal() + (_Vertical
? 0 : _TrackPos
));
892 _MouseDownOffsetY
= eventDesc
.getY() - (getYReal() + (_Vertical
? _TrackPos
: 0));
894 // if target is a menu, hidde its sub menus
895 if(_Target
&& _Target
->getParent())
897 CGroupSubMenuBase
*menu
= dynamic_cast<CGroupSubMenuBase
*>(_Target
->getParent());
899 menu
->hideSubMenus();
903 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouseleftup
)
906 runAH(_AHOnScrollEnd
, _AHOnScrollEndParams
.empty() ? _AHOnScrollParams
: _AHOnScrollEndParams
); // backward compatibility
909 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mouserightdown
&& _MouseDown
&& _Cancelable
)
912 setValue(_InitialValue
);
913 runAH(_AHOnScrollCancel
, _AHOnScrollCancelParams
); // backward compatibility
916 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousemove
)
920 sint32 dx
= eventDesc
.getX() - (getXReal() + (_Vertical
? 0 : _TrackPos
) + _MouseDownOffsetX
);
921 sint32 dy
= eventDesc
.getY() - (getYReal() + (_Vertical
? _TrackPos
: 0 ) + _MouseDownOffsetY
);
922 if (dx
!= 0) moveTrackX (dx
);
923 if (dy
!= 0) moveTrackY (dy
);
927 if (eventDesc
.getEventTypeExtended() == NLGUI::CEventDescriptorMouse::mousewheel
&& _Vertical
)
929 moveTargetY (-(eventDesc
.getWheel() * 12));
933 else if (event
.getType() == NLGUI::CEventDescriptor::key
)
935 const NLGUI::CEventDescriptorKey
&eventDesc
= (const NLGUI::CEventDescriptorKey
&)event
;
937 if (eventDesc
.getKeyEventType() == NLGUI::CEventDescriptorKey::keydown
)
943 if (eventDesc
.getKey() == KeyNEXT
) i
++;
944 else if (eventDesc
.getKey() == KeyPRIOR
) i
--;
949 moveTrackY(-(i
* _TargetStepY
));
951 moveTrackX(-(i
* _TargetStepX
));
960 // ------------------------------------------------------------------------------------------------
961 void CCtrlScroll::setTarget (CInterfaceGroup
*pIG
)
967 if (_Target
->getPosRef()&Hotspot_Tx
)
972 if (_Target
->getPosRef()&Hotspot_Tx
)
979 if (_Target
->getPosRef()&Hotspot_xL
)
984 if (_Target
->getPosRef()&Hotspot_xL
)
990 // ------------------------------------------------------------------------------------------------
991 sint32
CCtrlScroll::moveTrackX (sint32 dx
)
995 if ((getWReal()-_TrackSize
) <= 0)
999 float tpos
= _TrackPos
;
1000 sint32 tsize
= _TrackSize
;
1002 // Limit the scroller to the defined area
1003 newtpos
= tpos
+ dx
;
1004 if (newtpos
< 0) newtpos
= 0;
1005 if (newtpos
> (getWReal()-tsize
)) newtpos
= (getWReal()-tsize
);
1006 dx
= newtpos
- tpos
;
1010 _TrackPos
= newtpos
;
1012 computeTargetOfsFromPos();
1014 else // This is a number scroller
1016 float factor
= (float)(_Max
- _Min
);
1018 if (_Aligned
== 2) // LEFT
1019 factor
= -factor
* newtpos
/ (float)(getWReal()-tsize
) - _Min
;
1021 factor
= factor
* (1.0f
-(newtpos
/ (float)(getWReal()-tsize
))) + _Min
;
1023 _TrackPos
= newtpos
;
1025 if (_Aligned
== 2) // LEFT
1026 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1028 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1030 // step and clamp value
1031 normalizeValue(_Value
);
1035 if (_Aligned
== 2) // LEFT
1036 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
1038 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
1039 factor
*= (this->getWReal() - _TrackSize
);
1041 _TrackDispPos
= (sint32
)factor
;
1046 _ObserverOn
= false;
1047 _DBLink
.setSInt32 (_Value
);
1052 // Launch the scroller event if any
1053 runAH(_AHOnScroll
, _AHOnScrollParams
);
1058 // ------------------------------------------------------------------------------------------------
1059 sint32
CCtrlScroll::moveTrackY (sint32 dy
)
1063 if ((getHReal()-_TrackSize
) <= 0)
1067 float tpos
= _TrackPos
;
1068 sint32 tsize
= _TrackSize
;
1070 // Limit the scroller to the defined area
1071 newtpos
= tpos
+ dy
;
1072 if (newtpos
< 0) newtpos
= 0;
1073 if (newtpos
> (getHReal()-tsize
)) newtpos
= (getHReal()-tsize
);
1074 dy
= newtpos
- tpos
;
1078 _TrackPos
= newtpos
;
1080 computeTargetOfsFromPos();
1082 else // This is a number scroller
1084 float factor
= (float)(_Max
- _Min
);
1086 if (_Aligned
== 1) // BOTTOM
1087 factor
= -factor
* newtpos
/ (float)(getHReal()-tsize
) - _Min
;
1089 factor
= factor
* (1.0f
-(newtpos
/ (float)(getHReal()-tsize
))) + _Min
;
1091 _TrackPos
= newtpos
;
1093 if (_Aligned
== 1) // BOTTOM
1094 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1096 _Value
= (sint32
) (_Inverted
? factor
: -factor
);
1098 // step and clamp value
1099 normalizeValue(_Value
);
1103 if (_Aligned
== 1) // BOTTOM
1104 factor
= ((float)_Value
-_Min
) / (_Max
-_Min
);
1106 factor
= 1.0f
- ((float)_Value
-_Min
) / (_Max
-_Min
);
1107 factor
*= (this->getHReal() - _TrackSize
);
1109 _TrackDispPos
= (sint32
)factor
;
1114 _ObserverOn
= false;
1115 _DBLink
.setSInt32 (_Value
);
1120 // Launch the scroller event if any
1121 runAH(_AHOnScroll
, _AHOnScrollParams
);
1126 // ------------------------------------------------------------------------------------------------
1127 void CCtrlScroll::setTextureBottomOrLeft (const std::string
&txName
)
1129 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1130 _TxIdB
= rVR
.getTextureIdFromName(txName
);
1133 // ------------------------------------------------------------------------------------------------
1134 void CCtrlScroll::setTextureMiddle (const std::string
&txName
)
1136 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1137 _TxIdM
= rVR
.getTextureIdFromName(txName
);
1140 // ------------------------------------------------------------------------------------------------
1141 void CCtrlScroll::setTextureTopOrRight (const std::string
&txName
)
1143 CViewRenderer
&rVR
= *CViewRenderer::getInstance();
1144 _TxIdT
= rVR
.getTextureIdFromName(txName
);
1147 std::string
CCtrlScroll::getTextureBottomOrLeft() const
1149 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdB
);
1152 std::string
CCtrlScroll::getTextureMiddle() const
1154 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdM
);
1157 std::string
CCtrlScroll::getTextureTopOrRight() const
1159 return CViewRenderer::getInstance()->getTextureNameFromId( _TxIdT
);
1162 // ------------------------------------------------------------------------------------------------
1163 void CCtrlScroll::setValue(sint32 value
)
1165 normalizeValue(value
);
1169 _ObserverOn
= false;
1170 _DBLink
.setSInt32(value
);
1180 // ------------------------------------------------------------------------------------------------
1181 void CCtrlScroll::setTrackPos(sint32 pos
)
1185 moveTrackY(pos
- _TrackPos
);
1189 moveTrackX(pos
- _TrackPos
);
1194 // ------------------------------------------------------------------------------------------------
1195 void CCtrlScroll::computeTargetOfsFromPos()
1199 float factor
= ((float)_Target
->getHReal() - (float)_Target
->getMaxHReal());
1201 if (_Aligned
== 1) // BOTTOM
1202 factor
= -factor
* _TrackPos
/ favoid0((float)(getHReal()-_TrackSize
));
1204 factor
= factor
* (1.0f
-(_TrackPos
/ favoid0((float)(getHReal()-_TrackSize
))));
1206 // Compute Steped target
1207 sint32 nexOfsY
= (sint32
) floorf(0.5+(_Inverted
? factor
: -factor
));
1209 nexOfsY
= ((nexOfsY
+_TargetStepY
/2)/_TargetStepY
) * _TargetStepY
;
1210 _Target
->setOfsY (nexOfsY
);
1211 _LastTargetOfsY
= nexOfsY
;
1213 // invalidate only XReal/YReal, doing only 1 pass
1214 _Target
->invalidateCoords(1);
1218 float factor
= ((float)_Target
->getWReal() - (float)_Target
->getMaxWReal());
1220 if (_Aligned
== 2) // LEFT
1221 factor
= -factor
* _TrackPos
/ favoid0((float)(getWReal()-_TrackSize
));
1223 factor
= factor
* (1.0f
-(_TrackPos
/ favoid0((float)(getWReal()-_TrackSize
))));
1225 // Compute Steped target
1226 sint32 nexOfsX
= (sint32
) floorf(0.5+(_Inverted
? factor
: -factor
));
1228 nexOfsX
= ((nexOfsX
+_TargetStepX
/2)/_TargetStepX
) * _TargetStepX
;
1229 _Target
->setOfsX (nexOfsX
);
1230 _LastTargetOfsX
= nexOfsX
;
1232 // invalidate only XReal/YReal, doing only 1 pass
1233 _Target
->invalidateCoords(1);
1237 // ------------------------------------------------------------------------------------------------
1238 void CCtrlScroll::update(ICDBNode
* /* node */)
1240 if (!_ObserverOn
) return;
1241 _Value
= _DBLink
.getSInt32();
1242 // the value in the db changed
1243 invalidateCoords(1);
1244 if (_Target
) _Target
->invalidateCoords(1);
1248 // ***************************************************************************
1249 void CCtrlScroll::moveTargetX (sint32 dx
)
1253 sint32 maxWReal
= _Target
->getMaxWReal();
1254 sint32 wReal
= _Target
->getWReal();
1255 if(wReal
<= maxWReal
)
1258 // compute the new ofsX.
1259 sint32 ofsX
= _Target
->getOfsX();
1261 clamp(ofsX
, 0, wReal
-maxWReal
);
1262 _Target
->setOfsX(ofsX
);
1264 // compute new trackPos.
1265 if (_Aligned
== 2) // LEFT
1267 float factor
= (float)(wReal
-maxWReal
);
1268 factor
= -(float)ofsX
/ factor
;
1269 clamp(factor
, 0.f
, 1.f
);
1270 _TrackPos
= factor
* (getWReal()-_TrackSize
);
1274 float factor
= (float)(wReal
-maxWReal
);
1275 factor
= (float)ofsX
/ factor
;
1276 clamp(factor
, 0.f
, 1.f
);
1277 _TrackPos
= (1.0f
-factor
) * (getWReal() - _TrackSize
);
1280 // invalidate only position. 1 pass is sufficient
1281 invalidateCoords(1);
1284 // ***************************************************************************
1285 void CCtrlScroll::moveTargetY (sint32 dy
)
1289 sint32 maxHReal
= _Target
->getMaxHReal();
1290 sint32 hReal
= _Target
->getHReal();
1291 if(hReal
<= maxHReal
)
1294 if (_TargetStepY
> 1)
1296 sint sign
= (0 < dy
) - (dy
< 0);
1297 dy
= sign
* max(1, (dy
/ _TargetStepY
)) * _TargetStepY
;
1300 // compute the new ofsY.
1301 sint32 ofsY
= _Target
->getOfsY();
1304 // compute new trackPos.
1305 if (_Aligned
== 1) // BOTTOM
1307 clamp(ofsY
, maxHReal
- hReal
, 0);
1308 _Target
->setOfsY(ofsY
);
1309 float factor
= (float)(hReal
-maxHReal
);
1310 factor
= -(float)ofsY
/ factor
;
1311 clamp(factor
, 0.f
, 1.f
);
1312 _TrackPos
= factor
* (getHReal()-_TrackSize
);
1316 clamp(ofsY
, 0, hReal
-maxHReal
);
1317 _Target
->setOfsY(ofsY
);
1318 float factor
= (float)(hReal
-maxHReal
);
1319 factor
= (float)ofsY
/ factor
;
1320 clamp(factor
, 0.f
, 1.f
);
1321 _TrackPos
= (1.0f
-factor
) * (getHReal() - _TrackSize
);
1324 // invalidate only position. 1 pass is sufficient
1325 invalidateCoords(1);
1328 // ***************************************************************************
1329 void CCtrlScroll::normalizeValue(sint32
&value
)
1332 if(_StepValue
==0 || _StepValue
==1)
1334 // if interval is null, force min!
1341 // get range of possible position
1342 // sint32 size= _Max - _Min;
1345 sint32 val
= (value
+ (_StepValue
/2) -_Min
) / _StepValue
;
1346 val
= _Min
+ val
* _StepValue
;
1347 clamp(val
, _Min
, _Max
);
1351 // ***************************************************************************
1352 void CCtrlScroll::setFrozen (bool state
)
1362 // ------------------------------------------------------------------------------------------------
1363 int CCtrlScroll::luaEnsureVisible(CLuaState
&ls
)
1365 const char *funcName
= "ensureVisible";
1366 CLuaIHM::checkArgCount(ls
, funcName
, 3);
1367 CLuaIHM::checkArgTypeUIElement(ls
, funcName
, 1);
1368 CLuaIHM::checkArgType(ls
, funcName
, 2, LUA_TSTRING
);
1369 CLuaIHM::checkArgType(ls
, funcName
, 3, LUA_TSTRING
);
1371 std::string hsStr
[] = { ls
.toString(2), ls
.toString(3) };
1373 for (uint hsIndex
= 0; hsIndex
< 2; ++ hsIndex
)
1377 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "T") == 0)
1379 hs
[hsIndex
] = Hotspot_Tx
;
1382 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "M") == 0)
1384 hs
[hsIndex
] = Hotspot_Mx
;
1387 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "B") == 0)
1389 hs
[hsIndex
] = Hotspot_Bx
;
1393 hs
[hsIndex
] = Hotspot_Bx
;
1394 CLuaIHM::fails(ls
, "%s : couldn't parse hotspot for vertical scrollbar", funcName
);
1399 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "L") == 0)
1401 hs
[hsIndex
] = Hotspot_xL
;
1404 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "M") == 0)
1406 hs
[hsIndex
] = Hotspot_xM
;
1409 if (NLMISC::nlstricmp(hsStr
[hsIndex
], "R") == 0)
1411 hs
[hsIndex
] = Hotspot_xR
;
1415 hs
[hsIndex
] = Hotspot_xL
;
1416 CLuaIHM::fails(ls
, "%s : couldn't parse hotspot for horizontal scrollbar", funcName
);
1420 ensureVisible(CLuaIHM::getUIOnStack(ls
, 1), hs
[0], hs
[1]);
1425 // ------------------------------------------------------------------------------------------------
1426 void CCtrlScroll::ensureVisible(CInterfaceElement
*childElement
, THotSpot childHotSpot
, THotSpot parentHotSpot
)
1428 if (!_Target
) return; // not connected to a target yet
1429 if (!childElement
) return;
1430 // compute corners of interest for enclosed element & enclosing group
1431 sint32 childX
, childY
;
1432 childElement
->getCorner(childX
, childY
, childHotSpot
);
1435 sint32 maxHReal
= _Target
->getMaxHReal();
1436 sint32 hReal
= _Target
->getHReal();
1437 if(hReal
> maxHReal
)
1440 switch (parentHotSpot
)
1443 enclosingDY
= maxHReal
;
1446 enclosingDY
= maxHReal
/ 2;
1458 sint32 offsetY
= (_Target
->getYReal() + _Target
->getHReal() - childY
) - enclosingDY
;
1459 NLMISC::clamp(offsetY
, 0, hReal
- maxHReal
);
1460 _Target
->setOfsY(offsetY
);
1461 _Target
->invalidateCoords();
1463 else if (_Aligned
== 1)
1465 // Bottom aligned case
1466 sint32 offsetY
= (maxHReal
- enclosingDY
) - (childY
- _Target
->getYReal());
1467 NLMISC::clamp(offsetY
, maxHReal
- hReal
, 0);
1468 _Target
->setOfsY(offsetY
);
1469 _Target
->invalidateCoords();
1472 // else, ... fully visible (not occluded by parent group)
1476 sint32 maxWReal
= _Target
->getMaxWReal();
1477 sint32 wReal
= _Target
->getWReal();
1478 if(wReal
> maxWReal
)
1481 switch (parentHotSpot
)
1484 enclosingDX
= maxWReal
;
1487 enclosingDX
= maxWReal
/ 2;
1498 // right aligned case
1499 sint32 offsetX
= (_Target
->getXReal() + _Target
->getWReal() - childX
) - enclosingDX
;
1500 NLMISC::clamp(offsetX
, 0, wReal
- maxWReal
);
1501 _Target
->setOfsX(offsetX
);
1502 _Target
->invalidateCoords();
1504 else if (_Aligned
== 2)
1506 // Left aligned case
1507 sint32 offsetX
= (maxWReal
- enclosingDX
) - (childX
- _Target
->getXReal());
1508 NLMISC::clamp(offsetX
, maxWReal
- wReal
, 0);
1509 _Target
->setOfsX(offsetX
);
1510 _Target
->invalidateCoords();
1513 // else, ... fully visible (not occluded by parent group)