Index: binaries/data/mods/mod/gui/common/modern/setup.xml
===================================================================
--- binaries/data/mods/mod/gui/common/modern/setup.xml
+++ binaries/data/mods/mod/gui/common/modern/setup.xml
@@ -8,7 +8,7 @@
==========================================
-->
+
+
Index: binaries/data/mods/mod/gui/gui.rng
===================================================================
--- binaries/data/mods/mod/gui/gui.rng
+++ binaries/data/mods/mod/gui/gui.rng
@@ -331,18 +331,18 @@
-
-
-
-
+
-
+
+
+
+
@@ -677,7 +677,7 @@
-
+
Index: binaries/data/mods/mod/gui/modmod/styles.xml
===================================================================
--- binaries/data/mods/mod/gui/modmod/styles.xml
+++ binaries/data/mods/mod/gui/modmod/styles.xml
@@ -6,7 +6,7 @@
font="sans-13"
scrollbar="true"
scrollbar_style="ModernScrollBar"
- scroll_bottom="true"
+ scrollbar_sticky_end="true"
textcolor="white"
text_align="left"
text_valign="center"
Index: binaries/data/mods/public/gui/common/styles.xml
===================================================================
--- binaries/data/mods/public/gui/common/styles.xml
+++ binaries/data/mods/public/gui/common/styles.xml
@@ -88,7 +88,7 @@
font="sans-14"
scrollbar="true"
scrollbar_style="ModernScrollBar"
- scroll_bottom="false"
+ scrollbar_sticky_end="false"
textcolor="white"
text_align="left"
text_valign="top"
@@ -99,7 +99,7 @@
font="sans-13"
scrollbar="true"
scrollbar_style="ModernScrollBar"
- scroll_bottom="true"
+ scrollbar_sticky_end="true"
textcolor="white"
text_align="left"
/>
@@ -109,7 +109,7 @@
font="sans-13"
scrollbar="true"
scrollbar_style="ModernScrollBar"
- scroll_bottom="true"
+ scrollbar_sticky_end="true"
textcolor="white"
text_align="left"
/>
@@ -119,7 +119,7 @@
font="sans-bold-14"
scrollbar="true"
scrollbar_style="ModernScrollBar"
- scroll_bottom="true"
+ scrollbar_sticky_end="true"
textcolor="white"
text_align="left"
text_valign="center"
Index: binaries/data/mods/public/gui/credits/credits.xml
===================================================================
--- binaries/data/mods/public/gui/credits/credits.xml
+++ binaries/data/mods/public/gui/credits/credits.xml
@@ -20,7 +20,7 @@
Index: binaries/data/mods/public/gui/pregame/mainmenu.js
===================================================================
--- binaries/data/mods/public/gui/pregame/mainmenu.js
+++ binaries/data/mods/public/gui/pregame/mainmenu.js
@@ -18,6 +18,33 @@
g_BackgroundLayerData,
g_ProjectInformation,
g_CommunityButtons);
+
+
+ const tstCt = [ "blue", "red", "purple", "cyan", "rainbow", "tartan", "plaid", "brown", "black", "grey", "gray", "pink", "green", "magenta", "taupe", "mauve", "pecan", "orange" ];
+ const tstDd = Engine.GetGUIObjectByName("testDrop");
+ tstDd.list = tstCt;
+ tstDd.selected = 2;
+
+ const tstLt = Engine.GetGUIObjectByName("testList");
+ tstLt.list = tstCt;
+ tstLt.selected = 4;
+
+ const tstOLt = Engine.GetGUIObjectByName("testOList");
+ tstOLt.list_name = tstCt;
+ tstOLt.list_a = tstCt;
+ tstOLt.list_b = tstCt.reverse();
+ tstOLt.list = tstCt;
+ tstOLt.selected = 1;
+
+ const tstTxt = Engine.GetGUIObjectByName("testTextbox").caption;
+ const tstTB = Engine.GetGUIObjectByName("testTextboxScrollable");
+ for (let i = 0; i < 3; ++i)
+ tstTB.caption += '[font="sans-bold-12"]Scrollable [/font]' + tstTxt + "\n\n";
+
+ const tstML = Engine.GetGUIObjectByName("testInputMultiline");
+ for (let i = 0; i < 24; ++i)
+ tstML.caption += "\n.";
+ tstML.caption += "\nGroovy, baby!";
}
function getHotloadData()
Index: binaries/data/mods/public/gui/pregame/mainmenu.xml
===================================================================
--- binaries/data/mods/public/gui/pregame/mainmenu.xml
+++ binaries/data/mods/public/gui/pregame/mainmenu.xml
@@ -11,6 +11,31 @@
+
+
+
+
+
+[font="sans-bold-14"]Textbox:[/font]
+Consider yourself, at home!
+Consider yourself, part of the furniture!
+We've taken to you, so strong.
+It's clear. We're. Going to get along!
+
+
+
+
+
+
+
+
+
+ Single Line Input Box
+ Multiple Line Input Box
+
+
+
+
Index: source/gui/CGUI.h
===================================================================
--- source/gui/CGUI.h
+++ source/gui/CGUI.h
@@ -676,7 +676,7 @@
// Styles
std::map m_Styles;
- // Scroll-bar styles
+ // Scrollbar styles
std::map m_ScrollBarStyles;
// Icons
Index: source/gui/CGUI.cpp
===================================================================
--- source/gui/CGUI.cpp
+++ source/gui/CGUI.cpp
@@ -1185,13 +1185,13 @@
else
scrollbar.m_UseEdgeButtons = b;
}
- else if (attr_name == "width")
+ else if (attr_name == "breadth")
{
float f;
if (!ParseString(this, attr_value.FromUTF8(), f))
LOGERROR("GUI: Error parsing '%s' (\"%s\")", attr_name, attr_value);
else
- scrollbar.m_Width = f;
+ scrollbar.m_Breadth = f;
}
else if (attr_name == "minimum_bar_size")
{
Index: source/gui/CGUIScrollBarVertical.h
===================================================================
--- source/gui/CGUIScrollBarVertical.h
+++ source/gui/CGUIScrollBarVertical.h
@@ -16,9 +16,10 @@
*/
/*
- A GUI Scrollbar, this class doesn't present all functionality
- to the scrollbar, it just controls the drawing and a wrapper
- for interaction with it.
+ A vertical GUI Scrollbar, this class doesn't present all functionality
+ to the scrollbar, it just controls the drawing, handles some events,
+ and provides a wrapper for interaction with itself. Actual tracking
+ of how far we've scrolled inside the owner is handled elsewhere.
*/
#ifndef INCLUDED_CGUISCROLLBARVERTICAL
@@ -39,15 +40,19 @@
public:
/**
- * Draw the scroll-bar
+ * Draw the scrollbar
*/
virtual void Draw(CCanvas2D& canvas);
/**
- * If an object that contains a scrollbar has got messages, send
- * them to the scroll-bar and it will see if the message regarded
- * itself.
+ * Setup the scrollbar, setting the size, length and position.
*
+ * @see IGUIScrollBar#Setup()
+ */
+ virtual void Setup();
+ virtual void Setup(const CRect& content);
+
+ /**
* @see IGUIObject#HandleMessage()
*/
virtual void HandleMessage(SGUIMessage& Message);
@@ -81,14 +86,14 @@
/**
* Get the rectangle of the outline of the scrollbar, every component of the
- * scroll-bar should be inside this area.
+ * scrollbar should be inside this area.
* @return Rectangle, CRect
*/
virtual CRect GetOuterRect() const;
protected:
/**
- * Should the scroll bar proceed to the left or to the right of the m_X value.
+ * Should the scrollbar be drawn on the left or on the right of the m_X value.
* Notice, this has nothing to do with where the owner places it.
*/
bool m_RightAligned;
Index: source/gui/CGUIScrollBarVertical.cpp
===================================================================
--- source/gui/CGUIScrollBarVertical.cpp
+++ source/gui/CGUIScrollBarVertical.cpp
@@ -31,6 +31,26 @@
{
}
+void CGUIScrollBarVertical::Setup()
+{
+ CRect host = GetHostGUIObject().GetComputedSize();
+ CRect content = GetHostGUIObject().GetContentSize();
+
+ SetScrollRange(content.GetHeight());
+ Setup(host);
+}
+
+void CGUIScrollBarVertical::Setup(const CRect& content)
+{
+ SetScrollSpace(content.GetHeight());
+
+ SetX(m_RightAligned ? content.right : content.left);
+ SetY(content.top);
+ SetZ(GetHostGUIObject().GetBufferedZ());
+
+ SetLength(content.bottom - content.top);
+}
+
void CGUIScrollBarVertical::SetPosFromMousePos(const CVector2D& mouse)
{
if (!GetStyle())
@@ -42,7 +62,7 @@
float emptyBackground = m_Length - m_BarSize;
if (GetStyle()->m_UseEdgeButtons)
- emptyBackground -= GetStyle()->m_Width * 2;
+ emptyBackground -= GetStyle()->m_Breadth * 2;
m_Pos = m_PosWhenPressed + GetMaxPos() * (mouse.Y - m_BarPressedAtPos.Y) / emptyBackground;
}
@@ -51,11 +71,11 @@
{
if (!GetStyle())
{
- LOGWARNING("Attempt to draw scrollbar without a style.");
+ LOGWARNING("Attempt to draw a vertical scrollbar without a style.");
return;
}
- if (IsVisible())
+ if (IsNeeded())
{
CRect outline = GetOuterRect();
@@ -64,9 +84,9 @@
canvas,
CRect(
outline.left,
- outline.top + (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Width : 0),
+ outline.top + (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Breadth : 0),
outline.right,
- outline.bottom - (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Width : 0)
+ outline.bottom - (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Breadth : 0)
)
);
@@ -102,7 +122,7 @@
outline.left,
outline.top,
outline.right,
- outline.top+GetStyle()->m_Width
+ outline.top + GetStyle()->m_Breadth
)
);
@@ -111,7 +131,7 @@
canvas,
CRect(
outline.left,
- outline.bottom-GetStyle()->m_Width,
+ outline.bottom - GetStyle()->m_Breadth,
outline.right,
outline.bottom
)
@@ -128,6 +148,20 @@
void CGUIScrollBarVertical::HandleMessage(SGUIMessage& Message)
{
+ switch (Message.type)
+ {
+ case GUIM_MOUSE_WHEEL_UP:
+ ScrollMinus();
+ break;
+
+ case GUIM_MOUSE_WHEEL_DOWN:
+ ScrollPlus();
+ break;
+
+ default:
+ break;
+ }
+
IGUIScrollBar::HandleMessage(Message);
}
@@ -143,14 +177,14 @@
if (GetStyle()->m_UseEdgeButtons)
{
- from += GetStyle()->m_Width;
- to -= GetStyle()->m_Width;
+ from += GetStyle()->m_Breadth;
+ to -= GetStyle()->m_Breadth;
}
ret.top = from + (to - from) * m_Pos / GetMaxPos();
ret.bottom = ret.top + m_BarSize;
- ret.right = m_X + (m_RightAligned ? 0 : GetStyle()->m_Width);
- ret.left = ret.right - GetStyle()->m_Width;
+ ret.right = m_X + (m_RightAligned ? 0 : GetStyle()->m_Breadth);
+ ret.left = ret.right - GetStyle()->m_Breadth;
return ret;
}
@@ -162,9 +196,9 @@
return ret;
ret.top = m_Y;
- ret.bottom = m_Y+m_Length;
- ret.right = m_X + (m_RightAligned ? 0 : GetStyle()->m_Width);
- ret.left = ret.right - GetStyle()->m_Width;
+ ret.bottom = m_Y + m_Length;
+ ret.right = m_X + (m_RightAligned ? 0 : GetStyle()->m_Breadth);
+ ret.left = ret.right - GetStyle()->m_Breadth;
return ret;
}
@@ -174,12 +208,12 @@
if (!GetStyle())
return false;
- float StartX = m_RightAligned ? m_X-GetStyle()->m_Width : m_X;
+ float StartX = m_RightAligned ? m_X - GetStyle()->m_Breadth : m_X;
return mouse.X >= StartX &&
- mouse.X <= StartX + GetStyle()->m_Width &&
+ mouse.X <= StartX + GetStyle()->m_Breadth &&
mouse.Y >= m_Y &&
- mouse.Y <= m_Y + GetStyle()->m_Width;
+ mouse.Y <= m_Y + GetStyle()->m_Breadth;
}
bool CGUIScrollBarVertical::HoveringButtonPlus(const CVector2D& mouse)
@@ -187,10 +221,10 @@
if (!GetStyle())
return false;
- float StartX = m_RightAligned ? m_X-GetStyle()->m_Width : m_X;
+ float StartX = m_RightAligned ? m_X - GetStyle()->m_Breadth : m_X;
return mouse.X > StartX &&
- mouse.X < StartX + GetStyle()->m_Width &&
- mouse.Y > m_Y + m_Length - GetStyle()->m_Width &&
+ mouse.X < StartX + GetStyle()->m_Breadth &&
+ mouse.Y > m_Y + m_Length - GetStyle()->m_Breadth &&
mouse.Y < m_Y + m_Length;
}
Index: source/gui/IGUIScrollBar.h
===================================================================
--- source/gui/IGUIScrollBar.h
+++ source/gui/IGUIScrollBar.h
@@ -25,18 +25,19 @@
#define INCLUDED_IGUISCROLLBAR
#include "gui/CGUISprite.h"
+#include "gui/ObjectBases/IGUIScrollBarOwner.h"
#include "maths/Vector2D.h"
#include "ps/CStr.h"
class CCanvas2D;
class CGUI;
-class IGUIScrollBarOwner;
+class IGUIObject;
struct SGUIMessage;
/**
- * The GUI Scroll-bar style. Tells us how scroll-bars look and feel.
+ * The GUI Scrollbar style. Tells us how scrollbars look and feel.
*
- * A scroll-bar style can choose whether to support horizontal, vertical
+ * A scrollbar style can choose whether to support horizontal, vertical
* or both.
*
* @see IGUIScrollBar
@@ -54,9 +55,11 @@
//@{
/**
- * Width of bar, also both sides of the edge buttons.
+ * Breadth of bar, from side to side. It is the width of a vertical bar
+ * and the height of a horizontal bar. It is also used as the dimensions
+ * of both sides of the edge buttons.
*/
- float m_Width;
+ float m_Breadth;
/**
* Scrollable with the wheel.
@@ -83,7 +86,7 @@
float m_MinimumBarSize;
/**
- * Sometimes you would like your scroll bar to have a fixed maximum size
+ * Sometimes you would like your scrollbar to have a fixed maximum size
* so that the texture does not get too stretched, you can set a maximum
* in pixels.
*/
@@ -139,17 +142,17 @@
/**
- * The GUI Scroll-bar, used everywhere there is a scroll-bar in the game.
+ * The GUI Scrollbar, used everywhere there is a scrollbar in the game.
*
- * To include a scroll-bar to an object, inherent the object from
- * IGUIScrollBarOwner and call AddScrollBar() to add the scroll-bars.
+ * To include a scrollbar to an object, inherent the object from
+ * IGUIScrollBarOwner and call AddScrollBar() to add the scrollbars.
*
* It's also important that the scrollbar is located within the parent
* object's mouse over area. Otherwise the input won't be sent to the
- * scroll-bar.
+ * scrollbar.
*
- * The class does not provide all functionality to the scroll-bar, many
- * things the parent of the scroll-bar, must provide. Like a combo-box.
+ * The class does not provide all functionality to the scrollbar, many
+ * things the parent of the scrollbar, must provide. Like a combo-box.
*/
class IGUIScrollBar
{
@@ -161,19 +164,36 @@
public:
/**
- * Draw the scroll-bar
+ * Draw the scrollbar
*/
virtual void Draw(CCanvas2D& canvas) = 0;
/**
* If an object that contains a scrollbar has got messages, send
- * them to the scroll-bar and it will see if the message regarded
+ * them to the scrollbar and it will see if the message regarded
* itself.
*
* @see IGUIObject#HandleMessage()
*/
virtual void HandleMessage(SGUIMessage& Message) = 0;
+ /**
+ * Setup the scrollbar. Sets the size, length and position.
+ * An object owning scrollbars still has to call this (preferably
+ * in the object's own Setup function), it isn't called
+ * automatically. There are two variations covering several common
+ * uses.
+ *
+ * The first assumes that the content is inside the host and thus
+ * uses the host's dimensions.
+ *
+ * The second permits a CRect defining the dimensions of the
+ * scrollable content to be passed. Any object that uses this
+ * variant is required to explicitly set a scroll range.
+ */
+ virtual void Setup() = 0;
+ virtual void Setup(const CRect& content) = 0;
+
/**
* Set m_Pos with g_mouse_x/y input, i.e. when draggin.
*/
@@ -213,7 +233,7 @@
/**
* Scrollbars without height shouldn't be visible
*/
- bool IsVisible() const { return GetMaxPos() != 0.f; }
+ bool IsNeeded() const { return GetMaxPos() != 0.f; }
/**
* Increase scroll one step
@@ -236,16 +256,16 @@
virtual void ScrollMinusPlenty() { m_Pos -= 90.f; UpdatePosBoundaries(); }
/**
- * Set host object, must be done almost at creation of scroll bar.
+ * Set host object, must be done almost at creation of the scrollbar.
* @param pOwner Pointer to host object.
*/
void SetHostObject(IGUIScrollBarOwner* pOwner) { m_pHostObject = pOwner; }
/**
- * Set Width
- * @param width Width
+ * Set the Breadth of the scrollbar
+ * @param breadth Breadth
*/
- void SetWidth(float width) { m_Width = width; }
+ void SetBreadth(float breadth) { m_Breadth = breadth; }
/**
* Set X Position
@@ -266,7 +286,7 @@
void SetZ(float z) { m_Z = z; }
/**
- * Set Length of scroll bar
+ * Set the length of the scrollbar
* @param length Length
*/
void SetLength(float length) { m_Length = length; }
@@ -290,30 +310,37 @@
void SetBarPressed(bool b) { m_BarPressed = b; }
/**
- * Set Scroll bar style string
- * @param style String with scroll bar style reference name
+ * Set the scrollbar style
+ * @param style String consisting of the name of the scrollbar style
*/
void SetScrollBarStyle(const CStr& style) { m_ScrollBarStyle = style; }
/**
* Get style used by the scrollbar
- * @return Scroll bar style struct.
+ * @return Scrollbar style struct.
*/
const SGUIScrollBarStyle* GetStyle() const;
/**
- * Get the rectangle of the actual BAR. not the whole scroll-bar.
+ * Get the rectangle of the actual BAR. not the whole scrollbar.
* @return Rectangle, CRect
*/
virtual CRect GetBarRect() const = 0;
/**
* Get the rectangle of the outline of the scrollbar, every component of the
- * scroll-bar should be inside this area.
+ * scrollbar should be inside this area.
* @return Rectangle, CRect
*/
virtual CRect GetOuterRect() const = 0;
+ /**
+ * The difference between this and m_pHostObject is the latter is the ScrollBarOwner class,
+ * while this retuns the IGUIObject class, and as such has access to the object attributes
+ * set via JS, along with other attributes.
+ */
+ IGUIObject& GetHostGUIObject() { return m_pHostObject->m_pObject; }
+
protected:
/**
* Sets up bar size
@@ -333,9 +360,9 @@
//@{
/**
- * Width of the scroll bar
+ * Breadth of the scrollbar
*/
- float m_Width;
+ float m_Breadth;
/**
* Absolute X Position
@@ -373,15 +400,10 @@
float m_BarSize;
/**
- * Scroll bar style reference name
+ * Scrollbar style reference name
*/
CStr m_ScrollBarStyle;
- /**
- * Pointer to scroll bar style used.
- */
- SGUIScrollBarStyle* m_pStyle;
-
/**
* Host object, prerequisite!
*/
@@ -424,7 +446,7 @@
bool m_ButtonMinusPressed, m_ButtonPlusPressed;
/**
- * Position of scroll bar, 0 means scrolled all the way to one side.
+ * Position of the scrollbar, 0 means scrolled all the way to one side.
* It is measured in pixels, it is up to the host to make it actually
* apply in pixels.
*/
Index: source/gui/IGUIScrollBar.cpp
===================================================================
--- source/gui/IGUIScrollBar.cpp
+++ source/gui/IGUIScrollBar.cpp
@@ -26,10 +26,9 @@
IGUIScrollBar::IGUIScrollBar(CGUI& pGUI)
: m_pGUI(pGUI),
- m_pStyle(nullptr),
m_X(300.f), m_Y(300.f),
m_ScrollRange(1.f), m_ScrollSpace(0.f), // MaxPos: not 0, due to division.
- m_Length(200.f), m_Width(20.f),
+ m_Length(200.f), m_Breadth(20.f),
m_BarSize(0.f), m_Pos(0.f),
m_ButtonPlusPressed(false),
m_ButtonMinusPressed(false),
@@ -55,7 +54,7 @@
// Check for edge buttons
if (GetStyle()->m_UseEdgeButtons)
- length -= GetStyle()->m_Width * 2.f;
+ length -= GetStyle()->m_Breadth * 2.f;
// Check min and max are valid
if (min > length)
@@ -121,42 +120,37 @@
const CVector2D& mouse = m_pGUI.GetMousePos();
- // if bar is pressed
+ // If bar is pressed
if (GetBarRect().PointInside(mouse))
{
m_BarPressed = true;
m_BarPressedAtPos = mouse;
m_PosWhenPressed = m_Pos;
}
- // if button-minus is pressed
+ // If "minus" button is pressed
else if (m_ButtonMinusHovered)
{
m_ButtonMinusPressed = true;
ScrollMinus();
}
- // if button-plus is pressed
+ // If "plus" button is pressed
else if (m_ButtonPlusHovered)
{
m_ButtonPlusPressed = true;
ScrollPlus();
}
- // Pressing the background of the bar, to scroll
- // notice the if-sentence alone does not admit that,
- // it must be after the above if/elses
- else
+ // Pressing the background of the scrollbar
+ else if (GetOuterRect().PointInside(mouse))
{
- if (GetOuterRect().PointInside(mouse))
- {
- // Scroll plus or minus a lot, this might change, it doesn't
- // have to be fancy though.
- if (mouse.Y < GetBarRect().top)
- ScrollMinusPlenty();
- else
- ScrollPlusPlenty();
- // Simulate mouse movement to see if bar now is hovered
- SGUIMessage msg(GUIM_MOUSE_MOTION);
- HandleMessage(msg);
- }
+ // Scroll plus or minus a lot, this might change, it doesn't
+ // have to be fancy though.
+ if (mouse.Y < GetBarRect().top)
+ ScrollMinusPlenty();
+ else
+ ScrollPlusPlenty();
+ // Simulate mouse movement to see if bar now is hovered
+ SGUIMessage msg(GUIM_MOUSE_MOTION);
+ HandleMessage(msg);
}
break;
}
@@ -168,7 +162,10 @@
case GUIM_MOUSE_WHEEL_UP:
{
- ScrollMinus();
+ // If we're at the limit, pass the message to host object's parent.
+ if (m_Pos <= 0)
+ GetHostGUIObject().GetParent()->HandleMessage(Message);
+
// Since the scroll was changed, let's simulate a mouse movement
// to check if scrollbar now is hovered
SGUIMessage msg(GUIM_MOUSE_MOTION);
@@ -178,7 +175,10 @@
case GUIM_MOUSE_WHEEL_DOWN:
{
- ScrollPlus();
+ // If we're at the limit, pass the message to host object's parent.
+ if (m_Pos >= GetMaxPos())
+ GetHostGUIObject().GetParent()->HandleMessage(Message);
+
// Since the scroll was changed, let's simulate a mouse movement
// to check if scrollbar now is hovered
SGUIMessage msg(GUIM_MOUSE_MOTION);
Index: source/gui/ObjectBases/IGUIObject.h
===================================================================
--- source/gui/ObjectBases/IGUIObject.h
+++ source/gui/ObjectBases/IGUIObject.h
@@ -191,6 +191,11 @@
*/
CRect GetComputedSize();
+ /**
+ * Calculates and returns the size of the content of the object.
+ */
+ virtual const CRect GetContentSize() { return CRect(); };
+
virtual const CStrW& GetTooltipText() const { return m_Tooltip; }
virtual const CStr& GetTooltipStyle() const { return m_TooltipStyle; }
@@ -297,15 +302,6 @@
*/
bool ApplyStyle(const CStr& StyleName);
- /**
- * Returns not the Z value, but the actual buffered Z value, i.e. if it's
- * defined relative, then it will check its parent's Z value and add
- * the relativity.
- *
- * @return Actual Z value on the screen.
- */
- virtual float GetBufferedZ() const;
-
/**
* Add an object to the hierarchy.
*/
@@ -336,11 +332,14 @@
*/
void ReleaseFocus();
-protected:
/**
- * Check if object is focused.
+ * Returns not the Z value, but the actual buffered Z value, i.e. if it's
+ * defined relative, then it will check its parent's Z value and add
+ * the relativity.
+ *
+ * @return Actual Z value on the screen.
*/
- bool IsFocused() const;
+ virtual float GetBufferedZ() const;
/**
* NOTE! This will not just return m_pParent, when that is
@@ -353,6 +352,12 @@
*/
IGUIObject* GetParent() const;
+protected:
+ /**
+ * Check if object is focused.
+ */
+ bool IsFocused() const;
+
/**
* Handle additional children to the \-tag. In IGUIObject, this function does
* nothing. In CList and CDropDown, it handles the \, used to build the data.
Index: source/gui/ObjectBases/IGUIScrollBarOwner.h
===================================================================
--- source/gui/ObjectBases/IGUIScrollBarOwner.h
+++ source/gui/ObjectBases/IGUIScrollBarOwner.h
@@ -29,8 +29,8 @@
class IGUIObject;
/**
- * Base-class this if you want an object to contain
- * one, or several, scroll-bars.
+ * Base class if you want an object to contain
+ * one, or several, scrollbars.
*/
class IGUIScrollBarOwner
{
@@ -60,13 +60,13 @@
virtual const SGUIScrollBarStyle* GetScrollBarStyle(const CStr8& style) const;
/**
- * Add a scroll-bar
+ * Add a scrollbar
*/
virtual void AddScrollBar(std::unique_ptr scrollbar);
/**
- * Get Scroll Bar reference (it should be transparent it's actually
- * pointers).
+ * Get a scrollbar reference (it should be transparent it's actually a
+ * pointer).
*/
virtual IGUIScrollBar& GetScrollBar(const int& index)
{
@@ -74,11 +74,13 @@
}
/**
- * Get the position of the scroll bar at @param index.
+ * Get the position of the scrollbar at @param index.
* Equivalent to GetScrollbar(index).GetPos().
*/
virtual float GetScrollBarPos(const int index) const;
+ bool KeepScrollBarAtEnd(const int index) const;
+
protected:
/**
* Predominately you will only have one, but you can have
@@ -86,6 +88,8 @@
*/
std::vector> m_ScrollBars;
+ CGUISimpleSetting m_ScrollStickyEnd;
+
private:
/**
* Reference to the IGUIObject.
Index: source/gui/ObjectBases/IGUIScrollBarOwner.cpp
===================================================================
--- source/gui/ObjectBases/IGUIScrollBarOwner.cpp
+++ source/gui/ObjectBases/IGUIScrollBarOwner.cpp
@@ -24,7 +24,8 @@
#include "gui/ObjectBases/IGUIObject.h"
IGUIScrollBarOwner::IGUIScrollBarOwner(IGUIObject& pObject)
- : m_pObject(pObject)
+ : m_pObject(pObject),
+ m_ScrollStickyEnd(&pObject, "scrollbar_sticky_end", false)
{
}
@@ -63,3 +64,9 @@
{
return m_ScrollBars[index]->GetPos();
}
+
+bool IGUIScrollBarOwner::KeepScrollBarAtEnd(const int index) const
+{
+ // We use 1.5px delta so this is true when there's no content yet.
+ return m_ScrollStickyEnd && m_ScrollBars[index]->GetPos() > m_ScrollBars[index]->GetMaxPos() - 1.5f;
+}
Index: source/gui/ObjectTypes/CDropDown.cpp
===================================================================
--- source/gui/ObjectTypes/CDropDown.cpp
+++ source/gui/ObjectTypes/CDropDown.cpp
@@ -88,6 +88,7 @@
Message.value == "dropdown_buffer" ||
Message.value == "minimum_visible_items" ||
Message.value == "scrollbar_style" ||
+ Message.value == "scrollbar" ||
Message.value == "button_width")
{
SetupListRect();
@@ -114,8 +115,8 @@
for (int i = 0; i < static_cast(m_List->m_Items.size()); ++i)
{
if (mouse.Y >= rect.top + m_ItemsYPositions[i] &&
- mouse.Y < rect.top + m_ItemsYPositions[i+1] &&
- // mouse is not over scroll-bar
+ mouse.Y < rect.top + m_ItemsYPositions[i + 1] &&
+ // Mouse is not over scrollbar.
(m_HideScrollBar ||
mouse.X < GetScrollBar(0).GetOuterRect().left ||
mouse.X > GetScrollBar(0).GetOuterRect().right))
@@ -149,8 +150,8 @@
break;
}
- // We can't inherent this routine from CList, because we need to include
- // a mouse click to open the dropdown, also the coordinates are changed.
+ // We can't inheret this routine from CList, because we need to include
+ // a mouse click to open the dropdown. Also, the coordinates are changed.
case GUIM_MOUSE_PRESS_LEFT:
{
if (!m_Enabled)
Index: source/gui/ObjectTypes/CInput.h
===================================================================
--- source/gui/ObjectTypes/CInput.h
+++ source/gui/ObjectTypes/CInput.h
@@ -92,6 +92,8 @@
*/
virtual void UpdateCachedSize();
+ virtual const CRect GetContentSize();
+
/**
* Draws the Text
*/
@@ -194,8 +196,10 @@
bool m_SelectingText;
/**
- * Whether the cached text is currently valid (if not then SetupText will be called by Draw)
+ * Whether the cached texts are currently valid. If not, then an
+ * appropriate method to update it will be called by Draw.
*/
+ bool m_GeneratedTextValid;
bool m_GeneratedPlaceholderTextValid;
CGUIText m_GeneratedPlaceholderText;
Index: source/gui/ObjectTypes/CInput.cpp
===================================================================
--- source/gui/ObjectTypes/CInput.cpp
+++ source/gui/ObjectTypes/CInput.cpp
@@ -53,6 +53,7 @@
m_CursorVisState(true),
m_CursorBlinkRate(0.5),
m_ComposingText(),
+ m_GeneratedTextValid(false),
m_GeneratedPlaceholderTextValid(false),
m_iComposedLength(),
m_iComposedPos(),
@@ -893,20 +894,14 @@
{
case GUIM_SETTINGS_UPDATED:
{
- // Update scroll-bar
- // TODO Gee: (2004-09-01) Is this really updated each time it should?
if (m_ScrollBar &&
(Message.value == "size" ||
Message.value == "z" ||
Message.value == "absolute"))
{
- GetScrollBar(0).SetX(m_CachedActualSize.right);
- GetScrollBar(0).SetY(m_CachedActualSize.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
+ GetScrollBar(0).Setup();
}
- // Update scrollbar
if (Message.value == "scrollbar_style")
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
@@ -924,7 +919,7 @@
Message.value == "scrollbar" ||
Message.value == "scrollbar_style")
{
- UpdateText();
+ m_GeneratedTextValid = false;
}
if (Message.value == "multiline")
@@ -934,7 +929,7 @@
else
GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
- UpdateText();
+ m_GeneratedTextValid = false;
}
if (Message.value == "placeholder_text" ||
@@ -957,7 +952,7 @@
m_MultiLine &&
GetScrollBar(0).GetStyle())
{
- if (m_pGUI.GetMousePos().X > m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Width)
+ if (m_pGUI.GetMousePos().X > m_CachedActualSize.right - GetScrollBar(0).GetStyle()->m_Breadth)
break;
}
@@ -1114,11 +1109,8 @@
}
case GUIM_LOAD:
{
- GetScrollBar(0).SetX(m_CachedActualSize.right);
- GetScrollBar(0).SetY(m_CachedActualSize.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
+ GetScrollBar(0).Setup();
UpdateText();
UpdateAutoScroll();
@@ -1171,24 +1163,30 @@
void CInput::UpdateCachedSize()
{
- // If an ancestor's size changed, this will let us intercept the change and
- // update our scrollbar positions
+ // If an ancestor's size changed, this will let us flag that
+ // the text needs resizing/repositioning on the next Draw call.
IGUIObject::UpdateCachedSize();
- if (m_ScrollBar)
- {
- GetScrollBar(0).SetX(m_CachedActualSize.right);
- GetScrollBar(0).SetY(m_CachedActualSize.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
- }
-
+ m_GeneratedTextValid = false;
m_GeneratedPlaceholderTextValid = false;
}
+const CRect CInput::GetContentSize()
+{
+ CStrIntern font_name(m_Font->ToUTF8());
+ if (font_name.empty())
+ return CRect();
+ CFontMetrics font(font_name);
+ float height = m_CharacterPositions.size() * font.GetLineSpacing() + m_BufferZone * 2.f;
+ return CRect(0.0f, 0.0f, GetTextAreaWidth(), height);
+}
+
void CInput::Draw(CCanvas2D& canvas)
{
+ if (!m_GeneratedTextValid)
+ UpdateText();
+
if (m_CursorBlinkRate > 0.0)
{
// check if the cursor visibility state needs to be changed
@@ -1879,11 +1877,10 @@
// add the final row (even if empty)
m_CharacterPositions.insert(current_line, row);
+ m_GeneratedTextValid = true;
+
if (m_ScrollBar)
- {
- GetScrollBar(0).SetScrollRange(m_CharacterPositions.size() * font.GetLineSpacing() + m_BufferZone * 2.f);
- GetScrollBar(0).SetScrollSpace(m_CachedActualSize.GetHeight());
- }
+ GetScrollBar(0).Setup();
}
int CInput::GetMouseHoveringTextPosition() const
@@ -2018,7 +2015,7 @@
float CInput::GetTextAreaWidth()
{
if (m_ScrollBar && GetScrollBar(0).GetStyle())
- return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f - GetScrollBar(0).GetStyle()->m_Width;
+ return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f - GetScrollBar(0).GetStyle()->m_Breadth;
return m_CachedActualSize.GetWidth() - m_BufferZone * 2.f;
}
Index: source/gui/ObjectTypes/CList.h
===================================================================
--- source/gui/ObjectTypes/CList.h
+++ source/gui/ObjectTypes/CList.h
@@ -32,7 +32,7 @@
* text-object for each element, which will be managed
* by the IGUITextOwner structure.
*
- * A scroll-bar will appear when needed. This will be
+ * A scrollbar will appear when needed. This will be
* achieved with the IGUIScrollBarOwner structure.
*/
class CList : public IGUIObject, public IGUIScrollBarOwner, public IGUITextOwner
@@ -131,7 +131,6 @@
CGUISimpleSetting m_Font;
CGUISimpleSetting m_ScrollBar;
CGUISimpleSetting m_ScrollBarStyle;
- CGUISimpleSetting m_ScrollBottom;
CGUISimpleSetting m_SoundDisabled;
CGUISimpleSetting m_SoundSelected;
CGUISimpleSetting m_Sprite;
Index: source/gui/ObjectTypes/CList.cpp
===================================================================
--- source/gui/ObjectTypes/CList.cpp
+++ source/gui/ObjectTypes/CList.cpp
@@ -42,7 +42,6 @@
m_Font(this, "font"),
m_ScrollBar(this, "scrollbar", false),
m_ScrollBarStyle(this, "scrollbar_style"),
- m_ScrollBottom(this, "scroll_bottom", false),
m_SoundDisabled(this, "sound_disabled"),
m_SoundSelected(this, "sound_selected"),
m_Sprite(this, "sprite"),
@@ -59,7 +58,7 @@
m_List(this, "list"),
m_ListData(this, "list_data")
{
- // Add scroll-bar
+ // Add scrollbar
auto bar = std::make_unique(pGUI);
bar->SetRightAligned(true);
AddScrollBar(std::move(bar));
@@ -88,11 +87,8 @@
bool bottom = false;
if (m_ScrollBar && GetScrollBar(0).GetStyle())
{
- if (m_ScrollBottom && GetScrollBar(0).GetPos() > GetScrollBar(0).GetMaxPos() - 1.5f)
- bottom = true;
-
- // remove scrollbar if applicable
- width -= GetScrollBar(0).GetStyle()->m_Width;
+ bottom = KeepScrollBarAtEnd(0);
+ width -= GetScrollBar(0).GetStyle()->m_Breadth;
}
// Generate texts
@@ -123,17 +119,10 @@
m_ItemsYPositions[m_List->m_Items.size()] = buffered_y;
- // Setup scrollbar
if (m_ScrollBar)
{
GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back());
- GetScrollBar(0).SetScrollSpace(GetListRect().GetHeight());
-
- CRect rect = GetListRect();
- GetScrollBar(0).SetX(rect.right);
- GetScrollBar(0).SetY(rect.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(rect.bottom - rect.top);
+ GetScrollBar(0).Setup(GetListRect());
if (bottom)
GetScrollBar(0).SetPos(GetScrollBar(0).GetMaxPos());
@@ -156,7 +145,7 @@
{
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message);
- //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
+ IGUITextOwner::HandleMessage(Message);
m_Modified = false;
switch (Message.type)
@@ -176,16 +165,11 @@
ScriptEvent(EventNameSelectionChange);
}
- if (Message.value == "scrollbar")
+ if (Message.value == "scrollbar" || Message.value == "scrollbar_style")
SetupText();
- // Update scrollbar
if (Message.value == "scrollbar_style")
- {
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
- SetupText();
- }
-
break;
case GUIM_MOUSE_PRESS_LEFT:
@@ -235,16 +219,12 @@
}
case GUIM_LOAD:
- {
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
break;
- }
default:
break;
}
-
- IGUITextOwner::HandleMessage(Message);
}
InReaction CList::ManuallyHandleKeys(const SDL_Event_* ev)
@@ -354,7 +334,7 @@
m_ItemsYPositions[i] - scroll > rect.GetHeight())
continue;
- // Clipping area (we'll have to substract the scrollbar)
+ // Clipping area (we'll have to subtract the scrollbar)
CRect cliparea = GetListRect();
if (m_ScrollBar)
@@ -473,7 +453,7 @@
mouse.Y += scroll;
// Mouse is over scrollbar
- if (m_ScrollBar && GetScrollBar(0).IsVisible() &&
+ if (m_ScrollBar && GetScrollBar(0).IsNeeded() &&
mouse.X >= GetScrollBar(0).GetOuterRect().left &&
mouse.X <= GetScrollBar(0).GetOuterRect().right)
return -1;
Index: source/gui/ObjectTypes/COList.h
===================================================================
--- source/gui/ObjectTypes/COList.h
+++ source/gui/ObjectTypes/COList.h
@@ -48,7 +48,7 @@
*
* The list can be sorted dynamically by JS code when a
* heading is clicked.
- * A scroll-bar will appear when needed.
+ * A scrollbar will appear when needed.
*/
class COList : public CList
{
Index: source/gui/ObjectTypes/COList.cpp
===================================================================
--- source/gui/ObjectTypes/COList.cpp
+++ source/gui/ObjectTypes/COList.cpp
@@ -53,9 +53,10 @@
m_GeneratedTexts.clear();
m_TotalAvailableColumnWidth = GetListRect().GetWidth();
- // remove scrollbar if applicable
+
+ // Reduce width by the breadth of the scrollbar if applicable.
if (m_ScrollBar && GetScrollBar(0).GetStyle())
- m_TotalAvailableColumnWidth -= GetScrollBar(0).GetStyle()->m_Width;
+ m_TotalAvailableColumnWidth -= GetScrollBar(0).GetStyle()->m_Breadth;
m_HeadingHeight = SORT_SPRITE_DIM; // At least the size of the sorting sprite
@@ -104,14 +105,8 @@
if (m_ScrollBar)
{
- CRect rect = GetListRect();
GetScrollBar(0).SetScrollRange(m_ItemsYPositions.back());
- GetScrollBar(0).SetScrollSpace(rect.GetHeight());
-
- GetScrollBar(0).SetX(rect.right);
- GetScrollBar(0).SetY(rect.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(rect.bottom - rect.top);
+ GetScrollBar(0).Setup(GetListRect());
}
}
Index: source/gui/ObjectTypes/CText.h
===================================================================
--- source/gui/ObjectTypes/CText.h
+++ source/gui/ObjectTypes/CText.h
@@ -49,6 +49,8 @@
*/
CSize2D GetTextSize();
+ virtual const CRect GetContentSize();
+
virtual const CStrW& GetTooltipText() const;
protected:
/**
@@ -80,8 +82,7 @@
CGUISimpleSetting m_Font;
CGUISimpleSetting m_ScrollBar;
CGUISimpleSetting m_ScrollBarStyle;
- CGUISimpleSetting m_ScrollBottom;
- CGUISimpleSetting m_ScrollTop;
+ CGUISimpleSetting m_ScrollResetOnChange;
CGUISimpleSetting m_Sprite;
CGUISimpleSetting m_SpriteOverlay;
CGUISimpleSetting m_TextColor;
Index: source/gui/ObjectTypes/CText.cpp
===================================================================
--- source/gui/ObjectTypes/CText.cpp
+++ source/gui/ObjectTypes/CText.cpp
@@ -33,14 +33,13 @@
m_Font(this, "font"),
m_ScrollBar(this, "scrollbar", false),
m_ScrollBarStyle(this, "scrollbar_style"),
- m_ScrollBottom(this, "scroll_bottom"),
- m_ScrollTop(this, "scroll_top"),
+ m_ScrollResetOnChange(this, "scrollbar_reset_on_change"),
m_Sprite(this, "sprite"),
m_SpriteOverlay(this, "sprite_overlay"),
m_TextColor(this, "textcolor"),
m_TextColorDisabled(this, "textcolor_disabled")
{
- // Add scroll-bar
+ // Add scrollbar
auto bar = std::make_unique(pGUI);
bar->SetRightAligned(true);
AddScrollBar(std::move(bar));
@@ -59,40 +58,34 @@
return;
float width = m_CachedActualSize.GetWidth();
- // remove scrollbar if applicable
+
+ // Reduce width by scrollbar breadth if applicable.
if (m_ScrollBar && GetScrollBar(0).GetStyle())
- width -= GetScrollBar(0).GetStyle()->m_Width;
+ width -= GetScrollBar(0).GetStyle()->m_Breadth;
m_GeneratedTexts[0] = CGUIText(m_pGUI, m_Caption, m_Font, width, m_BufferZone, m_TextAlign, this);
if (!m_ScrollBar)
- CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]);
-
- // Setup scrollbar
- if (m_ScrollBar)
{
- // If we are currently scrolled to the bottom of the text,
- // then add more lines of text, update the scrollbar so we
- // stick to the bottom.
- // (Use 1.5px delta so this triggers the first time caption is set)
- bool bottom = false;
- if (m_ScrollBottom && GetScrollBar(0).GetPos() > GetScrollBar(0).GetMaxPos() - 1.5f)
- bottom = true;
-
- GetScrollBar(0).SetScrollRange(m_GeneratedTexts[0].GetSize().Height);
- GetScrollBar(0).SetScrollSpace(m_CachedActualSize.GetHeight());
-
- GetScrollBar(0).SetX(m_CachedActualSize.right);
- GetScrollBar(0).SetY(m_CachedActualSize.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
-
- if (bottom)
- GetScrollBar(0).SetPos(GetScrollBar(0).GetMaxPos());
-
- if (m_ScrollTop)
- GetScrollBar(0).SetPos(0.0f);
+ CalculateTextPosition(m_CachedActualSize, m_TextPos, m_GeneratedTexts[0]);
+ return;
}
+
+ bool bottom = false;
+ if (m_ScrollResetOnChange)
+ GetScrollBar(0).SetPos(0.0f);
+ else
+ // If we are currently scrolled to the bottom of the text, the UI designer has
+ // specified that we should "stick" to the bottom, and more lines of text are
+ // being added, then we need to update the scrollbar so we stay at the bottom.
+ // And we need to determine this before we renew the scrollbars after adding
+ // the text.
+ bottom = KeepScrollBarAtEnd(0);
+
+ GetScrollBar(0).Setup();
+
+ if (bottom)
+ GetScrollBar(0).SetPos(GetScrollBar(0).GetMaxPos());
}
void CText::ResetStates()
@@ -113,6 +106,13 @@
return m_GeneratedTexts[0].GetSize();
}
+const CRect CText::GetContentSize()
+{
+ if (m_GeneratedTexts.empty())
+ return CRect();
+ return m_GeneratedTexts[0].GetSize();
+}
+
const CStrW& CText::GetTooltipText() const
{
for (const CGUIText& text : m_GeneratedTexts)
@@ -131,56 +131,31 @@
{
IGUIObject::HandleMessage(Message);
IGUIScrollBarOwner::HandleMessage(Message);
- //IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
+ IGUITextOwner::HandleMessage(Message);
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
- if (Message.value == "scrollbar")
+ if (Message.value == "scrollbar" || Message.value == "scrollbar_style")
SetupText();
- // Update scrollbar
if (Message.value == "scrollbar_style")
- {
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
- SetupText();
- }
-
break;
case GUIM_MOUSE_WHEEL_DOWN:
- {
- GetScrollBar(0).ScrollPlus();
- // Since the scroll was changed, let's simulate a mouse movement
- // to check if scrollbar now is hovered
- SGUIMessage msg(GUIM_MOUSE_MOTION);
- HandleMessage(msg);
- break;
- }
case GUIM_MOUSE_WHEEL_UP:
- {
- GetScrollBar(0).ScrollMinus();
- // Since the scroll was changed, let's simulate a mouse movement
- // to check if scrollbar now is hovered
- SGUIMessage msg(GUIM_MOUSE_MOTION);
- HandleMessage(msg);
+ if (!m_ScrollBar)
+ m_pParent->HandleMessage(Message);
break;
- }
+
case GUIM_LOAD:
- {
- GetScrollBar(0).SetX(m_CachedActualSize.right);
- GetScrollBar(0).SetY(m_CachedActualSize.top);
- GetScrollBar(0).SetZ(GetBufferedZ());
- GetScrollBar(0).SetLength(m_CachedActualSize.bottom - m_CachedActualSize.top);
GetScrollBar(0).SetScrollBarStyle(m_ScrollBarStyle);
break;
- }
default:
break;
}
-
- IGUITextOwner::HandleMessage(Message);
}
void CText::Draw(CCanvas2D& canvas)
@@ -213,14 +188,14 @@
const CGUIColor& color = m_Enabled ? m_TextColor : m_TextColorDisabled;
if (m_ScrollBar)
+ {
DrawText(canvas, 0, color, m_CachedActualSize.TopLeft() - CVector2D(0.f, scroll), cliparea);
+ // Draw scrollbars on top of the content
+ IGUIScrollBarOwner::Draw(canvas);
+ }
else
DrawText(canvas, 0, color, m_TextPos, cliparea);
- // Draw scrollbars on top of the content
- if (m_ScrollBar)
- IGUIScrollBarOwner::Draw(canvas);
-
// Draw the overlays last
m_pGUI.DrawSprite(m_SpriteOverlay, canvas, m_CachedActualSize);
}