Browse Source

Normalized scrollbar step size, by default on.
UI code cleanup.

Lasse Öörni 15 years ago
parent
commit
abc4b39adb

+ 8 - 3
Bin/Data/Scripts/GraphicsTest.as

@@ -487,10 +487,15 @@ void handleUpdate(StringHash eventType, VariantMap& eventData)
                 params.maxFilter = 1.0f;
                 params.maxFilter = 1.0f;
             pipeline.setEdgeFilter(params);
             pipeline.setEdgeFilter(params);
         }
         }
-        
-        if ((input.getKeyPress(KEY_ESC)) && (ui.getFocusElement() is null))
-            engine.exit();
     }
     }
+    
+    if (input.getKeyPress(KEY_ESC))
+	{
+		if (ui.getFocusElement() is null)
+	        engine.exit();
+	    else
+		    console.setVisible(false);
+	}
 }
 }
 
 
 void handleKeyDown(StringHash eventType, VariantMap& eventData)
 void handleKeyDown(StringHash eventType, VariantMap& eventData)

+ 8 - 3
Bin/Data/Scripts/NinjaSnowWar.as

@@ -59,9 +59,6 @@ void start()
 void runFrame()
 void runFrame()
 {
 {
     engine.runFrame(gameScene, gameCamera, !paused);
     engine.runFrame(gameScene, gameCamera, !paused);
-
-    if (input.getKeyPress(KEY_ESC))
-        engine.exit();
 }
 }
 
 
 void initAudio()
 void initAudio()
@@ -216,6 +213,14 @@ void handleUpdate(StringHash eventType, VariantMap& eventData)
             messageText.setText("");
             messageText.setText("");
     }
     }
 
 
+    if (input.getKeyPress(KEY_ESC))
+	{
+		if (!console.isVisible())
+	        engine.exit();
+	    else
+		    console.setVisible(false);
+	}
+
     if (!paused)
     if (!paused)
         updateControls();
         updateControls();
 }
 }

+ 0 - 2
Bin/Data/UI/TestLayout.xml

@@ -31,8 +31,6 @@
         <wordwrap enable="true" />
         <wordwrap enable="true" />
     </element>
     </element>
     <element type="ScrollView">
     <element type="ScrollView">
-        <position value="150 100" />
-        <size value="212 112" />
         <contentelement name="ScrollViewText" />
         <contentelement name="ScrollViewText" />
     </element>
     </element>
     <element type="LineEdit">
     <element type="LineEdit">

+ 16 - 10
Bin/Data/UI/TestLayout3.xml

@@ -32,6 +32,13 @@
     </element>
     </element>
     <element type="Element">
     <element type="Element">
         <layout orientation="horizontal" horizontal="resizechildren" vertical="resizechildren" spacing="8" />
         <layout orientation="horizontal" horizontal="resizechildren" vertical="resizechildren" spacing="8" />
+    	<element type="Text" name="ScrollViewText" >
+	        <position value="1 0" />
+	        <minsize value="300 400" />
+	        <font name="times.ttf" size="15" />
+            <text value="At some point the fire had started.\n  There was total chaos. The locks of the wooden barracks had been blown apart by gunfire from shotguns and assault rifles, and the trainees were pouring out in confusion. But the primary target still lay ahead.\n  The administrative building. Where the identities and evaluations of the trainees were stored.\n  That was first class knowledge. If the Agents could bring that knowledge to the public, and cross-reference the records - mostly boys of young age - with lists of known missing persons, then they could prove the existence of SCEPTRE." />
+	        <wordwrap enable="true" />
+	    </element>
         <element type="Button">
         <element type="Button">
             <element type="Text">
             <element type="Text">
                 <text value="TEST4" />
                 <text value="TEST4" />
@@ -39,6 +46,12 @@
                 <alignment horizontal="center" vertical="center" />
                 <alignment horizontal="center" vertical="center" />
             </element>
             </element>
         </element>
         </element>
+    	<element type="ScrollView">
+	        <contentelement name="ScrollViewText" />
+	        <scrollpanel>
+	        	<layout orientation="vertical" horizontal="resizechildren" vertical="resizechildren" border="1 1 1 1" spacing="0" />
+	        </scrollpanel>
+	    </element>
         <element type="Button">
         <element type="Button">
             <element type="Text">
             <element type="Text">
                 <text value="TEST5" />
                 <text value="TEST5" />
@@ -46,33 +59,26 @@
                 <alignment horizontal="center" vertical="center" />
                 <alignment horizontal="center" vertical="center" />
             </element>
             </element>
         </element>
         </element>
-        <element type="Button">
-            <element type="Text">
-                <text value="TEST6" />
-                <font name="cour.ttf" size="12" />
-                <alignment horizontal="center" vertical="center" />
-            </element>
-        </element>
     </element>
     </element>
     <element type="Element">
     <element type="Element">
         <layout orientation="horizontal" horizontal="resizechildren" vertical="resizechildren" spacing="8" />
         <layout orientation="horizontal" horizontal="resizechildren" vertical="resizechildren" spacing="8" />
         <element type="Button">
         <element type="Button">
             <element type="Text">
             <element type="Text">
-                <text value="TEST7" />
+                <text value="TEST6" />
                 <font name="cour.ttf" size="12" />
                 <font name="cour.ttf" size="12" />
                 <alignment horizontal="center" vertical="center" />
                 <alignment horizontal="center" vertical="center" />
             </element>
             </element>
         </element>
         </element>
         <element type="Button">
         <element type="Button">
             <element type="Text">
             <element type="Text">
-                <text value="TEST8" />
+                <text value="TEST7" />
                 <font name="cour.ttf" size="12" />
                 <font name="cour.ttf" size="12" />
                 <alignment horizontal="center" vertical="center" />
                 <alignment horizontal="center" vertical="center" />
             </element>
             </element>
         </element>
         </element>
         <element type="Button">
         <element type="Button">
             <element type="Text">
             <element type="Text">
-                <text value="TEST9" />
+                <text value="TEST8" />
                 <font name="cour.ttf" size="12" />
                 <font name="cour.ttf" size="12" />
                 <alignment horizontal="center" vertical="center" />
                 <alignment horizontal="center" vertical="center" />
             </element>
             </element>

+ 1 - 0
Engine/Engine/Console.cpp

@@ -67,6 +67,7 @@ Console::Console(Engine* engine) :
         
         
         mLineEdit = new LineEdit();
         mLineEdit = new LineEdit();
         mLineEdit->setColor(Color(0.0f, 0.0f, 0.0f, 0.5f));
         mLineEdit->setColor(Color(0.0f, 0.0f, 0.0f, 0.5f));
+        mLineEdit->getTextElement()->setSelectionColor(Color(0.0f, 0.5f, 0.0f, 0.75f));
         mLineEdit->setFocusMode(FM_FOCUSABLE); // Do not allow defocus with ESC
         mLineEdit->setFocusMode(FM_FOCUSABLE); // Do not allow defocus with ESC
         mBackground->addChild(mLineEdit);
         mBackground->addChild(mLineEdit);
         
         

+ 1 - 0
Engine/Engine/RegisterTemplates.h

@@ -490,6 +490,7 @@ template <class T> void registerUIElement(asIScriptEngine* engine, const char* c
     engine->RegisterObjectMethod(className, "UIElement@+ getChild(uint) const", asMETHODPR(T, getChild, (unsigned) const, UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getChild(uint) const", asMETHODPR(T, getChild, (unsigned) const, UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getChild(const string& in, bool) const", asMETHODPR(T, getChild, (const std::string&, bool) const, UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getChild(const string& in, bool) const", asMETHODPR(T, getChild, (const std::string&, bool) const, UIElement*), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getParent() const", asMETHOD(T, getParent), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getParent() const", asMETHOD(T, getParent), asCALL_THISCALL);
+    engine->RegisterObjectMethod(className, "UIElement@+ getOrigin() const", asMETHOD(T, getOrigin), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getRootElement() const", asMETHOD(T, getRootElement), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "UIElement@+ getRootElement() const", asMETHOD(T, getRootElement), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "XMLElement getStyleElement(XMLFile@+) const", asMETHODPR(T, getStyleElement, (XMLFile*) const, XMLElement), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "XMLElement getStyleElement(XMLFile@+) const", asMETHODPR(T, getStyleElement, (XMLFile*) const, XMLElement), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "IntVector2 screenToElement(const IntVector2& in)", asMETHOD(T, screenToElement), asCALL_THISCALL);
     engine->RegisterObjectMethod(className, "IntVector2 screenToElement(const IntVector2& in)", asMETHOD(T, screenToElement), asCALL_THISCALL);

+ 8 - 0
Engine/Engine/RegisterUI.cpp

@@ -123,6 +123,7 @@ static void registerSlider(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Slider", "void setOrientation(Orientation)", asMETHOD(Slider, setOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "void setOrientation(Orientation)", asMETHOD(Slider, setOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "void setRange(float)", asMETHOD(Slider, setRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "void setRange(float)", asMETHOD(Slider, setRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "void setValue(float)", asMETHOD(Slider, setValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "void setValue(float)", asMETHOD(Slider, setValue), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Slider", "void changeValue(float)", asMETHOD(Slider, changeValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "Orientation getOrientation() const", asMETHOD(Slider, getOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "Orientation getOrientation() const", asMETHOD(Slider, getOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "float getRange() const", asMETHOD(Slider, getRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "float getRange() const", asMETHOD(Slider, getRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "float getValue() const", asMETHOD(Slider, getValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("Slider", "float getValue() const", asMETHOD(Slider, getValue), asCALL_THISCALL);
@@ -136,11 +137,16 @@ static void registerScrollBar(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ScrollBar", "void setOrientation(Orientation)", asMETHOD(ScrollBar, setOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setOrientation(Orientation)", asMETHOD(ScrollBar, setOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setRange(float)", asMETHOD(ScrollBar, setRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setRange(float)", asMETHOD(ScrollBar, setRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setValue(float)", asMETHOD(ScrollBar, setValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setValue(float)", asMETHOD(ScrollBar, setValue), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollBar", "void changeValue(float)", asMETHOD(ScrollBar, changeValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setScrollStep(float)", asMETHOD(ScrollBar, setScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "void setScrollStep(float)", asMETHOD(ScrollBar, setScrollStep), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollBar", "void setNormalizeScrollStep(bool)", asMETHOD(ScrollBar, setNormalizeScrollStep), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollBar", "void stepBack()", asMETHOD(ScrollBar, stepBack), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollBar", "void stepForward()", asMETHOD(ScrollBar, stepForward), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Orientation getOrientation() const", asMETHOD(ScrollBar, getOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Orientation getOrientation() const", asMETHOD(ScrollBar, getOrientation), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getRange() const", asMETHOD(ScrollBar, getRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getRange() const", asMETHOD(ScrollBar, getRange), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getValue() const", asMETHOD(ScrollBar, getValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getValue() const", asMETHOD(ScrollBar, getValue), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getScrollStep() const", asMETHOD(ScrollBar, getScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "float getScrollStep() const", asMETHOD(ScrollBar, getScrollStep), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollBar", "bool getNormalizeScrollStep() const", asMETHOD(ScrollBar, getNormalizeScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Button@+ getBackButton() const", asMETHOD(ScrollBar, getBackButton), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Button@+ getBackButton() const", asMETHOD(ScrollBar, getBackButton), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Button@+ getForwardButton() const", asMETHOD(ScrollBar, getForwardButton), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Button@+ getForwardButton() const", asMETHOD(ScrollBar, getForwardButton), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Slider@+ getSlider() const", asMETHOD(ScrollBar, getSlider), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollBar", "Slider@+ getSlider() const", asMETHOD(ScrollBar, getSlider), asCALL_THISCALL);
@@ -155,6 +161,7 @@ static void registerScrollView(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ScrollView", "void setScrollBarsVisible(bool, bool)", asMETHOD(ScrollView, setScrollBarsVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "void setScrollBarsVisible(bool, bool)", asMETHOD(ScrollView, setScrollBarsVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "void setScrollStep(float)", asMETHOD(ScrollView, setScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "void setScrollStep(float)", asMETHOD(ScrollView, setScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "void setPageStep(float)", asMETHOD(ScrollView, setPageStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "void setPageStep(float)", asMETHOD(ScrollView, setPageStep), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollView", "void setNormalizeScrollStep(bool)", asMETHOD(ScrollView, setNormalizeScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "const IntVector2& getViewPosition() const", asMETHOD(ScrollView, getViewPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "const IntVector2& getViewPosition() const", asMETHOD(ScrollView, getViewPosition), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "UIElement@+ getElement() const", asMETHOD(ScrollView, getElement), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "UIElement@+ getElement() const", asMETHOD(ScrollView, getElement), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "ScrollBar@+ getHorizontalScrollBar() const", asMETHOD(ScrollView, getHorizontalScrollBar), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "ScrollBar@+ getHorizontalScrollBar() const", asMETHOD(ScrollView, getHorizontalScrollBar), asCALL_THISCALL);
@@ -164,6 +171,7 @@ static void registerScrollView(asIScriptEngine* engine)
     engine->RegisterObjectMethod("ScrollView", "bool getVerticalScrollBarVisible() const", asMETHOD(ScrollView, getVerticalScrollBarVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "bool getVerticalScrollBarVisible() const", asMETHOD(ScrollView, getVerticalScrollBarVisible), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "float getScrollStep() const", asMETHOD(ScrollView, getScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "float getScrollStep() const", asMETHOD(ScrollView, getScrollStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "float getPageStep() const", asMETHOD(ScrollView, getPageStep), asCALL_THISCALL);
     engine->RegisterObjectMethod("ScrollView", "float getPageStep() const", asMETHOD(ScrollView, getPageStep), asCALL_THISCALL);
+    engine->RegisterObjectMethod("ScrollView", "bool getNormalizeScrollStep() const", asMETHOD(ScrollView, getNormalizeScrollStep), asCALL_THISCALL);
     registerRefCasts<UIElement, ScrollView>(engine, "UIElement", "ScrollView");
     registerRefCasts<UIElement, ScrollView>(engine, "UIElement", "ScrollView");
 }
 }
 
 

+ 44 - 9
Engine/UI/ScrollBar.cpp

@@ -27,12 +27,14 @@
 #include "Slider.h"
 #include "Slider.h"
 #include "UIEvents.h"
 #include "UIEvents.h"
 
 
+static const float DEFAULT_SCROLL_STEP = 0.05f;
 static const float DEFAULT_REPEAT_DELAY = 0.4f;
 static const float DEFAULT_REPEAT_DELAY = 0.4f;
 static const float DEFAULT_REPEAT_RATE = 20.0f;
 static const float DEFAULT_REPEAT_RATE = 20.0f;
 
 
 ScrollBar::ScrollBar(const std::string& name) :
 ScrollBar::ScrollBar(const std::string& name) :
     UIElement(name),
     UIElement(name),
-    mScrollStep(0.1f),
+    mScrollStep(DEFAULT_SCROLL_STEP),
+    mNormalizeScrollStep(true),
     mLeftRect(IntRect::sZero),
     mLeftRect(IntRect::sZero),
     mRightRect(IntRect::sZero),
     mRightRect(IntRect::sZero),
     mUpRect(IntRect::sZero),
     mUpRect(IntRect::sZero),
@@ -66,6 +68,17 @@ void ScrollBar::setStyle(const XMLElement& element, ResourceCache* cache)
 {
 {
     UIElement::setStyle(element, cache);
     UIElement::setStyle(element, cache);
     
     
+    if (element.hasChildElement("scrollstep"))
+        setScrollStep(element.getChildElement("scrollstep").getFloat("value"));
+    if (element.hasChildElement("normalizescrollstep"))
+        setNormalizeScrollStep(element.getChildElement("normalizescrollstep").getBool("enable"));
+    if (element.hasChildElement("range"))
+    {
+        XMLElement rangeElem = element.getChildElement("range");
+        setRange(rangeElem.getFloat("max"));
+        setValue(rangeElem.getFloat("value"));
+    }
+    
     XMLElement backButtonElem = element.getChildElement("backbutton");
     XMLElement backButtonElem = element.getChildElement("backbutton");
     if (backButtonElem)
     if (backButtonElem)
     {
     {
@@ -98,12 +111,6 @@ void ScrollBar::setStyle(const XMLElement& element, ResourceCache* cache)
     if (sliderElem)
     if (sliderElem)
         mSlider->setStyle(sliderElem, cache);
         mSlider->setStyle(sliderElem, cache);
     
     
-    if (element.hasChildElement("range"))
-    {
-        XMLElement rangeElem = element.getChildElement("range");
-        setRange(rangeElem.getFloat("max"));
-        setValue(rangeElem.getFloat("value"));
-    }
     if (element.hasChildElement("orientation"))
     if (element.hasChildElement("orientation"))
     {
     {
         std::string orientation = element.getChildElement("orientation").getStringLower("value");
         std::string orientation = element.getChildElement("orientation").getStringLower("value");
@@ -164,11 +171,31 @@ void ScrollBar::setValue(float value)
     mSlider->setValue(value);
     mSlider->setValue(value);
 }
 }
 
 
+void ScrollBar::changeValue(float delta)
+{
+    mSlider->changeValue(delta);
+}
+
 void ScrollBar::setScrollStep(float step)
 void ScrollBar::setScrollStep(float step)
 {
 {
     mScrollStep = max(step, 0.0f);
     mScrollStep = max(step, 0.0f);
 }
 }
 
 
+void ScrollBar::setNormalizeScrollStep(bool enable)
+{
+    mNormalizeScrollStep = enable;
+}
+
+void ScrollBar::stepBack()
+{
+    mSlider->setValue(mSlider->getValue() - getEffectiveScrollStep());
+}
+
+void ScrollBar::stepForward()
+{
+    mSlider->setValue(mSlider->getValue() + getEffectiveScrollStep());
+}
+
 Orientation ScrollBar::getOrientation() const
 Orientation ScrollBar::getOrientation() const
 {
 {
     return mSlider->getOrientation();
     return mSlider->getOrientation();
@@ -184,14 +211,22 @@ float ScrollBar::getValue() const
     return mSlider->getValue();
     return mSlider->getValue();
 }
 }
 
 
+float ScrollBar::getEffectiveScrollStep() const
+{
+    if (!mNormalizeScrollStep)
+        return mScrollStep;
+    else
+        return mScrollStep * (mSlider->getRange() + 1.0f);
+}
+
 void ScrollBar::handleBackButtonPressed(StringHash eventType, VariantMap& eventData)
 void ScrollBar::handleBackButtonPressed(StringHash eventType, VariantMap& eventData)
 {
 {
-    mSlider->setValue(mSlider->getValue() - mScrollStep);
+    stepBack();
 }
 }
 
 
 void ScrollBar::handleForwardButtonPressed(StringHash eventType, VariantMap& eventData)
 void ScrollBar::handleForwardButtonPressed(StringHash eventType, VariantMap& eventData)
 {
 {
-    mSlider->setValue(mSlider->getValue() + mScrollStep);
+    stepForward();
 }
 }
 
 
 void ScrollBar::handleSliderChanged(StringHash eventType, VariantMap& eventData)
 void ScrollBar::handleSliderChanged(StringHash eventType, VariantMap& eventData)

+ 14 - 0
Engine/UI/ScrollBar.h

@@ -50,8 +50,16 @@ public:
     void setRange(float range);
     void setRange(float range);
     //! Set slider current value
     //! Set slider current value
     void setValue(float value);
     void setValue(float value);
+    //! Change slider current value by a delta
+    void changeValue(float delta);
     //! Set button scroll step
     //! Set button scroll step
     void setScrollStep(float step);
     void setScrollStep(float step);
+    //! Set whether scroll step is normalized to slider range
+    void setNormalizeScrollStep(bool enable);
+    //! Scroll back one step
+    void stepBack();
+    //! Scroll forward one step
+    void stepForward();
     
     
     //! Return orientation type
     //! Return orientation type
     Orientation getOrientation() const;
     Orientation getOrientation() const;
@@ -61,6 +69,10 @@ public:
     float getValue() const;
     float getValue() const;
     //! Return button scroll step
     //! Return button scroll step
     float getScrollStep() const { return mScrollStep; }
     float getScrollStep() const { return mScrollStep; }
+    //! Return effective scroll step, taking possible normalization into account
+    float getEffectiveScrollStep() const;
+    //! Return whether scroll step is normalized to slider range
+    bool getNormalizeScrollStep() const { return mNormalizeScrollStep; }
     //! Return back button element
     //! Return back button element
     Button* getBackButton() const { return mBackButton; }
     Button* getBackButton() const { return mBackButton; }
     //! Return forward button element
     //! Return forward button element
@@ -77,6 +89,8 @@ protected:
     SharedPtr<Slider> mSlider;
     SharedPtr<Slider> mSlider;
     //! Scroll step
     //! Scroll step
     float mScrollStep;
     float mScrollStep;
+    //! Normalize scroll step flag
+    bool mNormalizeScrollStep;
     //! Left button image rect
     //! Left button image rect
     IntRect mLeftRect;
     IntRect mLeftRect;
     //! Right button image rect
     //! Right button image rect

+ 27 - 32
Engine/UI/ScrollView.cpp

@@ -34,9 +34,9 @@ ScrollView::ScrollView(const std::string& name) :
     UIElement(name),
     UIElement(name),
     mViewPosition(IntVector2::sZero),
     mViewPosition(IntVector2::sZero),
     mViewSize(IntVector2::sZero),
     mViewSize(IntVector2::sZero),
-    mScrollStep(0.1f),
     mPageStep(1.0f)
     mPageStep(1.0f)
 {
 {
+    mClipChildren = true;
     mEnabled = true;
     mEnabled = true;
     mFocusMode = FM_FOCUSABLE_DEFOCUSABLE;
     mFocusMode = FM_FOCUSABLE_DEFOCUSABLE;
     
     
@@ -58,7 +58,6 @@ ScrollView::ScrollView(const std::string& name) :
     subscribeToEvent(mHorizontalScrollBar, EVENT_VISIBLECHANGED, EVENT_HANDLER(ScrollView, handleScrollBarVisibleChanged));
     subscribeToEvent(mHorizontalScrollBar, EVENT_VISIBLECHANGED, EVENT_HANDLER(ScrollView, handleScrollBarVisibleChanged));
     subscribeToEvent(mVerticalScrollBar, EVENT_SCROLLBARCHANGED, EVENT_HANDLER(ScrollView, handleScrollBarChanged));
     subscribeToEvent(mVerticalScrollBar, EVENT_SCROLLBARCHANGED, EVENT_HANDLER(ScrollView, handleScrollBarChanged));
     subscribeToEvent(mVerticalScrollBar, EVENT_VISIBLECHANGED, EVENT_HANDLER(ScrollView, handleScrollBarVisibleChanged));
     subscribeToEvent(mVerticalScrollBar, EVENT_VISIBLECHANGED, EVENT_HANDLER(ScrollView, handleScrollBarVisibleChanged));
-    subscribeToEvent(EVENT_TRYFOCUS, EVENT_HANDLER(ScrollView, handleTryFocus));
 }
 }
 
 
 ScrollView::~ScrollView()
 ScrollView::~ScrollView()
@@ -75,6 +74,8 @@ void ScrollView::setStyle(const XMLElement& element, ResourceCache* cache)
         setScrollStep(element.getChildElement("scrollstep").getFloat("value"));
         setScrollStep(element.getChildElement("scrollstep").getFloat("value"));
     if (element.hasChildElement("pagestep"))
     if (element.hasChildElement("pagestep"))
         setScrollStep(element.getChildElement("pagestep").getFloat("value"));
         setScrollStep(element.getChildElement("pagestep").getFloat("value"));
+    if (element.hasChildElement("normalizescrollstep"))
+        setNormalizeScrollStep(element.getChildElement("normalizescrollstep").getBool("enable"));
     
     
     XMLElement horizElem = element.getChildElement("horizontalscrollbar");
     XMLElement horizElem = element.getChildElement("horizontalscrollbar");
     if (horizElem)
     if (horizElem)
@@ -106,7 +107,7 @@ void ScrollView::onKey(int key, int buttons, int qualifiers)
             if (qualifiers & QUAL_CTRL)
             if (qualifiers & QUAL_CTRL)
                 mHorizontalScrollBar->setValue(0.0f);
                 mHorizontalScrollBar->setValue(0.0f);
             else
             else
-                mHorizontalScrollBar->setValue(mHorizontalScrollBar->getValue() - mScrollStep);
+                mHorizontalScrollBar->stepBack();
         }
         }
         break;
         break;
         
         
@@ -116,7 +117,7 @@ void ScrollView::onKey(int key, int buttons, int qualifiers)
             if (qualifiers & QUAL_CTRL)
             if (qualifiers & QUAL_CTRL)
                 mHorizontalScrollBar->setValue(mHorizontalScrollBar->getRange());
                 mHorizontalScrollBar->setValue(mHorizontalScrollBar->getRange());
             else
             else
-                mHorizontalScrollBar->setValue(mHorizontalScrollBar->getValue() + mScrollStep);
+                mHorizontalScrollBar->stepForward();
         }
         }
         break;
         break;
         
         
@@ -126,7 +127,7 @@ void ScrollView::onKey(int key, int buttons, int qualifiers)
             if (qualifiers & QUAL_CTRL)
             if (qualifiers & QUAL_CTRL)
                 mVerticalScrollBar->setValue(0.0f);
                 mVerticalScrollBar->setValue(0.0f);
             else
             else
-                mVerticalScrollBar->setValue(mVerticalScrollBar->getValue() - mScrollStep);
+                mVerticalScrollBar->stepBack();
         }
         }
         break;
         break;
         
         
@@ -136,18 +137,18 @@ void ScrollView::onKey(int key, int buttons, int qualifiers)
             if (qualifiers & QUAL_CTRL)
             if (qualifiers & QUAL_CTRL)
                 mVerticalScrollBar->setValue(mVerticalScrollBar->getRange());
                 mVerticalScrollBar->setValue(mVerticalScrollBar->getRange());
             else
             else
-                mVerticalScrollBar->setValue(mVerticalScrollBar->getValue() + mScrollStep);
+                mVerticalScrollBar->stepForward();
         }
         }
         break;
         break;
         
         
     case KEY_PAGEUP:
     case KEY_PAGEUP:
         if (mVerticalScrollBar)
         if (mVerticalScrollBar)
-            mVerticalScrollBar->setValue(mVerticalScrollBar->getValue() - mPageStep);
+            mVerticalScrollBar->changeValue(-mPageStep);
         break;
         break;
         
         
     case KEY_PAGEDOWN:
     case KEY_PAGEDOWN:
         if (mVerticalScrollBar)
         if (mVerticalScrollBar)
-            mVerticalScrollBar->setValue(mVerticalScrollBar->getValue() + mPageStep);
+            mVerticalScrollBar->changeValue(mPageStep);
         break;
         break;
     
     
     case KEY_HOME:
     case KEY_HOME:
@@ -216,7 +217,8 @@ void ScrollView::setScrollBarsVisible(bool horizontal, bool vertical)
 
 
 void ScrollView::setScrollStep(float step)
 void ScrollView::setScrollStep(float step)
 {
 {
-    mScrollStep = max(step, 0.0f);
+    mHorizontalScrollBar->setScrollStep(step);
+    mVerticalScrollBar->setScrollStep(step);
 }
 }
 
 
 void ScrollView::setPageStep(float step)
 void ScrollView::setPageStep(float step)
@@ -224,6 +226,12 @@ void ScrollView::setPageStep(float step)
     mPageStep = max(step, 0.0f);
     mPageStep = max(step, 0.0f);
 }
 }
 
 
+void ScrollView::setNormalizeScrollStep(bool enable)
+{
+    mHorizontalScrollBar->setNormalizeScrollStep(enable);
+    mVerticalScrollBar->setNormalizeScrollStep(enable);
+}
+
 bool ScrollView::getHorizontalScrollBarVisible() const
 bool ScrollView::getHorizontalScrollBarVisible() const
 {
 {
     return mHorizontalScrollBar->isVisible();
     return mHorizontalScrollBar->isVisible();
@@ -234,6 +242,16 @@ bool ScrollView::getVerticalScrollBarVisible() const
     return mVerticalScrollBar->isVisible();
     return mVerticalScrollBar->isVisible();
 }
 }
 
 
+float ScrollView::getScrollStep() const
+{
+    return mHorizontalScrollBar->getScrollStep();
+}
+
+bool ScrollView::getNormalizeScrollStep() const
+{
+    return mHorizontalScrollBar->getNormalizeScrollStep();
+}
+
 void ScrollView::updateViewSize()
 void ScrollView::updateViewSize()
 {
 {
     IntVector2 size(IntVector2::sZero);
     IntVector2 size(IntVector2::sZero);
@@ -307,26 +325,3 @@ void ScrollView::handleElementResized(StringHash eventType, VariantMap& eventDat
 {
 {
     updateViewSize();
     updateViewSize();
 }
 }
-
-void ScrollView::handleTryFocus(StringHash eventType, VariantMap& eventData)
-{
-    using namespace TryFocus;
-    
-    UIElement* focusElement = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
-    if ((!focusElement) || (focusElement == this))
-        return;
-    
-    // If the element is a non-focusable child of the ScrollView, divert focus to the ScrollView
-    if (focusElement->getFocusMode() < FM_FOCUSABLE)
-    {
-        while (focusElement)
-        {
-            focusElement = focusElement->getParent();
-            if (focusElement == this)
-            {
-                eventData[P_ELEMENT] = (void*)this;
-                return;
-            }
-        }
-    }
-}

+ 7 - 5
Engine/UI/ScrollView.h

@@ -55,11 +55,13 @@ public:
     void setViewPosition(int x, int y);
     void setViewPosition(int x, int y);
     //! Set scrollbars' visibility
     //! Set scrollbars' visibility
     void setScrollBarsVisible(bool horizontal, bool vertical);
     void setScrollBarsVisible(bool horizontal, bool vertical);
-    //! Set arrow key scroll step
+    //! Set arrow key scroll step. Also sets it on the scrollbars
     void setScrollStep(float step);
     void setScrollStep(float step);
     //! Set arrow key page step
     //! Set arrow key page step
     void setPageStep(float step);
     void setPageStep(float step);
-    
+    //! Set whether scroll step is normalized to content size
+    void setNormalizeScrollStep(bool enable);
+
     //! Return view offset from the top-left corner
     //! Return view offset from the top-left corner
     const IntVector2& getViewPosition() const { return mViewPosition; }
     const IntVector2& getViewPosition() const { return mViewPosition; }
     //! Return content element
     //! Return content element
@@ -75,9 +77,11 @@ public:
     //! Return vertical scrollbar visibility
     //! Return vertical scrollbar visibility
     bool getVerticalScrollBarVisible() const;
     bool getVerticalScrollBarVisible() const;
     //! Return arrow key scroll step
     //! Return arrow key scroll step
-    float getScrollStep() const { return mScrollStep; }
+    float getScrollStep() const;
     //! Return arrow key page step
     //! Return arrow key page step
     float getPageStep() const { return mPageStep; }
     float getPageStep() const { return mPageStep; }
+    //! Return whether scroll step is normalized to content size
+    bool getNormalizeScrollStep() const;
     
     
 protected:
 protected:
     //! Update view size from the content element
     //! Update view size from the content element
@@ -99,8 +103,6 @@ protected:
     IntVector2 mViewPosition;
     IntVector2 mViewPosition;
     //! Total view size
     //! Total view size
     IntVector2 mViewSize;
     IntVector2 mViewSize;
-    //! Arrow key scroll step
-    float mScrollStep;
     //! Arrow key page step
     //! Arrow key page step
     float mPageStep;
     float mPageStep;
     //! Ignore scrollbar events flag. Used to prevent possible endless loop when setting position
     //! Ignore scrollbar events flag. Used to prevent possible endless loop when setting position

+ 5 - 0
Engine/UI/Slider.cpp

@@ -161,6 +161,11 @@ void Slider::setValue(float value)
     }
     }
 }
 }
 
 
+void Slider::changeValue(float delta)
+{
+    setValue(mValue + delta);
+}
+
 void Slider::updateSlider()
 void Slider::updateSlider()
 {
 {
     if (mOrientation == O_HORIZONTAL)
     if (mOrientation == O_HORIZONTAL)

+ 2 - 0
Engine/UI/Slider.h

@@ -58,6 +58,8 @@ public:
     void setRange(float range);
     void setRange(float range);
     //! Set slider current value
     //! Set slider current value
     void setValue(float value);
     void setValue(float value);
+    //! Change value by a delta
+    void changeValue(float delta);
     
     
     //! Return orientation type
     //! Return orientation type
     Orientation getOrientation() const { return mOrientation; }
     Orientation getOrientation() const { return mOrientation; }

+ 16 - 6
Engine/UI/UI.cpp

@@ -121,12 +121,22 @@ void UI::setFocusElement(UIElement* element)
     // The event receivers may divert the focus
     // The event receivers may divert the focus
     element = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
     element = static_cast<UIElement*>(eventData[P_ELEMENT].getPtr());
     
     
-    // Return if already has focus
-    if ((element) && (element->hasFocus()))
-        return;
-    // Return if element can not be focused, and does not reset the focus either
-    if ((element) && (element->getFocusMode() == FM_NOTFOCUSABLE))
-        return;
+    if (element)
+    {
+        // Return if already has focus
+        if (element->hasFocus())
+            return;
+        // If element can not be focused, and does not reset the focus either, search toward the parent
+        for (;;)
+        {
+            if (element->getFocusMode() != FM_NOTFOCUSABLE)
+                break;
+            element = element->getParent();
+            // Return if did not find any parent element that changes the focus
+            if (!element)
+                return;
+        }
+    }
     
     
     std::vector<UIElement*> allChildren = mRootElement->getChildren(true);
     std::vector<UIElement*> allChildren = mRootElement->getChildren(true);