mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 05:13:58 -07:00
Add scrollpanel widget
This PR introduces a new ScrollPanel component with the following capabilities: - Scroll Orientation Support: Allows scrolling in horizontal, vertical, or both directions, providing flexibility for different use cases. - Partial Object Rendering: Supports partial rendering of objects that are only partially visible within the scroll boundaries, improving visual accuracy and performance. - Boundary-Constrained Mouse Interaction: Handles mouse events strictly within the panel's visible boundaries, preventing interaction with objects outside the scrollable area. - Minimum Internal Size (min_width, min_height): Introduces support for virtual space management, allowing the panel to maintain a minimum internal size independent of its actual on-screen dimensions. Even when the panel is resized, this ensures that the content respects a defined virtual space (with min_width and min_height), effectively simulating a larger internal canvas. This is particularly useful for large content or scenarios where a more extensive scrollable area is required than the current visible panel.
This commit is contained in:
parent
d98c93b35e
commit
8c250568e7
41 changed files with 1238 additions and 183 deletions
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4f229151ac93b005f69b5752e716c21ee8fd22b84f9e99912e8fc84f5ed4461f
|
||||
size 680
|
||||
|
|
@ -11,8 +11,10 @@
|
|||
minimum_bar_size = "15"
|
||||
maximum_bar_size = "15"
|
||||
show_edge_buttons = "false"
|
||||
sprite_back_vertical = "ModernScrollBack"
|
||||
sprite_bar_vertical = "ModernScrollBar"
|
||||
sprite_back_vertical = "ModernScrollbarVerticalBackground"
|
||||
sprite_slider_vertical = "ModernScrollbarVerticalSlider"
|
||||
sprite_back_horizontal = "ModernScrollbarHorizontalBackground"
|
||||
sprite_slider_horizontal = "ModernScrollbarHorizontalSlider"
|
||||
/>
|
||||
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
- Scrollbar -
|
||||
==========================================
|
||||
-->
|
||||
<sprite name = "ModernScrollBack">
|
||||
<sprite name = "ModernScrollbarVerticalBackground">
|
||||
<image backcolor="43 42 40"
|
||||
size="0 0 100% 100%"
|
||||
/>
|
||||
|
|
@ -14,12 +14,34 @@
|
|||
<image backcolor="0 0 0" size="0 100%-1 100% 100%"/>
|
||||
<image backcolor="0 0 0" size="0 0 1 100%"/>
|
||||
<image backcolor="0 0 0" size="100%-1 0 100% 100%"/>
|
||||
<image texture = "global/modern/scrollback.png"
|
||||
<image texture = "global/modern/scroll-background-vertical.png"
|
||||
real_texture_placement = "0 0 15 128"
|
||||
size = "0 0 100% 100%"
|
||||
/>
|
||||
</sprite>
|
||||
<sprite name = "ModernScrollBar">
|
||||
|
||||
<sprite name = "ModernScrollbarHorizontalBackground">
|
||||
<image backcolor="43 42 40"
|
||||
size="0 0 100% 100%"
|
||||
/>
|
||||
<image backcolor="0 0 0" size="0 0 100% 1"/>
|
||||
<image backcolor="0 0 0" size="0 100%-1 100% 100%"/>
|
||||
<image backcolor="0 0 0" size="0 0 1 100%"/>
|
||||
<image backcolor="0 0 0" size="100%-1 0 100% 100%"/>
|
||||
<image texture = "global/modern/scroll-background-horizontal.png"
|
||||
real_texture_placement = "0 0 128 15"
|
||||
size = "0 0 100% 100%"
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
<sprite name = "ModernScrollbarVerticalSlider">
|
||||
<image texture = "global/modern/scrollbar.png"
|
||||
real_texture_placement = "0 0 15 15"
|
||||
size = "0 0 100% 100%"
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
<sprite name = "ModernScrollbarHorizontalSlider">
|
||||
<image texture = "global/modern/scrollbar.png"
|
||||
real_texture_placement = "0 0 15 15"
|
||||
size = "0 0 100% 100%"
|
||||
|
|
|
|||
|
|
@ -508,6 +508,21 @@
|
|||
<optional>
|
||||
<attribute name="tooltip_style"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="orientation">
|
||||
<choice>
|
||||
<value>horizontal</value>
|
||||
<value>vertical</value>
|
||||
<value>both</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="min_width"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="min_height"/>
|
||||
</optional>
|
||||
</interleave>
|
||||
</define>
|
||||
<define name="objects">
|
||||
|
|
@ -759,17 +774,29 @@
|
|||
<attribute name="sprite_button_bottom_over"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_bar_vertical"/>
|
||||
<attribute name="sprite_slider_vertical"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_bar_vertical_over"/>
|
||||
<attribute name="sprite_slider_vertical_over"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_bar_vertical_pressed"/>
|
||||
<attribute name="sprite_slider_vertical_pressed"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_back_vertical"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_slider_horizontal"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_slider_horizontal_over"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_slider_horizontal_pressed"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<attribute name="sprite_back_horizontal"/>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</define>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "CGUI.h"
|
||||
|
||||
#include "GUIObjectEventBroadcaster.h"
|
||||
|
||||
#include "graphics/Canvas2D.h"
|
||||
#include "gui/IGUIScrollBar.h"
|
||||
#include "gui/ObjectBases/IGUIObject.h"
|
||||
|
|
@ -27,8 +29,6 @@
|
|||
#include "gui/Scripting/ScriptFunctions.h"
|
||||
#include "gui/Scripting/JSInterface_GUIProxy.h"
|
||||
#include "i18n/L10n.h"
|
||||
#include "lib/allocators/DynamicArena.h"
|
||||
#include "lib/allocators/STLAllocators.h"
|
||||
#include "lib/bits.h"
|
||||
#include "lib/input.h"
|
||||
#include "lib/sysdep/sysdep.h"
|
||||
|
|
@ -48,6 +48,7 @@
|
|||
#include "scriptinterface/ScriptInterface.h"
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
|
|
@ -63,38 +64,13 @@ const CStr CGUI::EventNameMouseRightPress = "MouseRightPress";
|
|||
const CStr CGUI::EventNameMouseLeftPress = "MouseLeftPress";
|
||||
const CStr CGUI::EventNameMouseWheelDown = "MouseWheelDown";
|
||||
const CStr CGUI::EventNameMouseWheelUp = "MouseWheelUp";
|
||||
const CStr CGUI::EventNameMouseWheelLeft = "MouseWheelLeft";
|
||||
const CStr CGUI::EventNameMouseWheelRight = "MouseWheelRight";
|
||||
const CStr CGUI::EventNameMouseLeftDoubleClick = "MouseLeftDoubleClick";
|
||||
const CStr CGUI::EventNameMouseLeftRelease = "MouseLeftRelease";
|
||||
const CStr CGUI::EventNameMouseRightDoubleClick = "MouseRightDoubleClick";
|
||||
const CStr CGUI::EventNameMouseRightRelease = "MouseRightRelease";
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct VisibleObject
|
||||
{
|
||||
IGUIObject* object;
|
||||
// Index of the object in a depth-first search inside GUI tree.
|
||||
u32 index;
|
||||
// Cached value of GetBufferedZ to avoid recursive calls in a deep hierarchy.
|
||||
float bufferedZ;
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
void CollectVisibleObjectsRecursively(const std::vector<IGUIObject*>& objects, Container* visibleObjects)
|
||||
{
|
||||
for (IGUIObject* const& object : objects)
|
||||
{
|
||||
if (!object->IsHidden())
|
||||
{
|
||||
visibleObjects->emplace_back(VisibleObject{object, static_cast<u32>(visibleObjects->size()), 0.0f});
|
||||
CollectVisibleObjectsRecursively(object->GetChildren(), visibleObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonynous namespace
|
||||
|
||||
CGUI::CGUI(ScriptContext& context)
|
||||
: m_BaseObject(std::make_unique<CGUIDummyObject>(*this)),
|
||||
m_FocusedObject(nullptr),
|
||||
|
|
@ -158,7 +134,7 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
|||
m_MousePos = CVector2D((float)ev->ev.motion.x / g_VideoMode.GetScale(), (float)ev->ev.motion.y / g_VideoMode.GetScale());
|
||||
|
||||
SGUIMessage msg(GUIM_MOUSE_MOTION);
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::HandleMessage, msg);
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhostOrOutOfBoundaries, &IGUIObject::HandleMessage, msg);
|
||||
}
|
||||
|
||||
// Update m_MouseButtons. (BUTTONUP is handled later.)
|
||||
|
|
@ -196,7 +172,7 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
|||
// Now we'll call UpdateMouseOver on *all* objects,
|
||||
// we'll input the one hovered, and they will each
|
||||
// update their own data and send messages accordingly
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest));
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhostOrOutOfBoundaries, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest));
|
||||
|
||||
if (ev->ev.type == SDL_MOUSEBUTTONDOWN)
|
||||
{
|
||||
|
|
@ -225,6 +201,11 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
|||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_DOWN, EventNameMouseWheelDown);
|
||||
else if (ev->ev.wheel.y > 0)
|
||||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_UP, EventNameMouseWheelUp);
|
||||
|
||||
if (ev->ev.wheel.x < 0)
|
||||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_LEFT, EventNameMouseWheelLeft);
|
||||
else if (ev->ev.wheel.x > 0)
|
||||
ret = pNearest->SendMouseEvent(GUIM_MOUSE_WHEEL_RIGHT, EventNameMouseWheelRight);
|
||||
}
|
||||
else if (ev->ev.type == SDL_MOUSEBUTTONUP)
|
||||
{
|
||||
|
|
@ -258,7 +239,7 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
|||
m_BaseObject->RecurseObject(&IGUIObject::IsHidden, &IGUIObject::ResetStates);
|
||||
|
||||
// Since the hover state will have been reset, we reload it.
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest));
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhostOrOutOfBoundaries, &IGUIObject::UpdateMouseOver, static_cast<IGUIObject* const&>(pNearest));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -298,7 +279,7 @@ InReaction CGUI::HandleEvent(const SDL_Event_* ev)
|
|||
|
||||
void CGUI::TickObjects()
|
||||
{
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::Tick);
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhostOrOutOfBoundaries, &IGUIObject::Tick);
|
||||
SendEventToAll(EventNameTick);
|
||||
m_Tooltip.Update(FindObjectUnderMouse(), m_MousePos, *this);
|
||||
}
|
||||
|
|
@ -327,32 +308,18 @@ void CGUI::SendEventToAll(const CStr& eventName, const JS::HandleValueArray& par
|
|||
|
||||
void CGUI::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
using Arena = Allocators::DynamicArena<128 * KiB>;
|
||||
using ObjectListAllocator = ProxyAllocator<VisibleObject, Arena>;
|
||||
Arena arena;
|
||||
|
||||
std::vector<VisibleObject, ObjectListAllocator> visibleObjects((ObjectListAllocator(arena)));
|
||||
CollectVisibleObjectsRecursively(m_BaseObject->GetChildren(), &visibleObjects);
|
||||
for (VisibleObject& visibleObject : visibleObjects)
|
||||
visibleObject.bufferedZ = visibleObject.object->GetBufferedZ();
|
||||
|
||||
std::sort(visibleObjects.begin(), visibleObjects.end(), [](const VisibleObject& visibleObject1, const VisibleObject& visibleObject2) -> bool {
|
||||
if (visibleObject1.bufferedZ != visibleObject2.bufferedZ)
|
||||
return visibleObject1.bufferedZ < visibleObject2.bufferedZ;
|
||||
return visibleObject1.index < visibleObject2.index;
|
||||
});
|
||||
|
||||
for (const VisibleObject& visibleObject : visibleObjects)
|
||||
visibleObject.object->Draw(canvas);
|
||||
CGUIObjectEventBroadcaster::RecurseVisibleObject(m_BaseObject.get(), &IGUIObject::Draw, canvas);
|
||||
}
|
||||
|
||||
void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, CCanvas2D& canvas, const CRect& Rect, const CRect& UNUSED(Clipping))
|
||||
void CGUI::DrawSprite(const CGUISpriteInstance& Sprite, CCanvas2D& canvas, const CRect& Rect, const CRect& Clipping)
|
||||
{
|
||||
// If the sprite doesn't exist (name == ""), don't bother drawing anything
|
||||
if (!Sprite)
|
||||
return;
|
||||
|
||||
// TODO: Clipping?
|
||||
std::optional<CCanvas2D::ScopedScissor> scopedScissor;
|
||||
if (Clipping != CRect())
|
||||
scopedScissor.emplace(canvas, Clipping);
|
||||
|
||||
Sprite.Draw(*this, canvas, Rect, m_Sprites);
|
||||
}
|
||||
|
|
@ -414,7 +381,7 @@ IGUIObject* CGUI::FindObjectByName(const CStr& Name) const
|
|||
IGUIObject* CGUI::FindObjectUnderMouse()
|
||||
{
|
||||
IGUIObject* pNearest = nullptr;
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::ChooseMouseOverAndClosest, pNearest);
|
||||
m_BaseObject->RecurseObject(&IGUIObject::IsHiddenOrGhostOrOutOfBoundaries, &IGUIObject::ChooseMouseOverAndClosest, pNearest);
|
||||
return pNearest;
|
||||
}
|
||||
|
||||
|
|
@ -1237,12 +1204,20 @@ void CGUI::Xeromyces_ReadScrollBarStyle(const XMBData& xmb, XMBElement element)
|
|||
scrollbar.m_SpriteButtonBottomOver = attr_value;
|
||||
else if (attr_name == "sprite_back_vertical")
|
||||
scrollbar.m_SpriteBackVertical = attr_value;
|
||||
else if (attr_name == "sprite_bar_vertical")
|
||||
scrollbar.m_SpriteBarVertical = attr_value;
|
||||
else if (attr_name == "sprite_bar_vertical_over")
|
||||
scrollbar.m_SpriteBarVerticalOver = attr_value;
|
||||
else if (attr_name == "sprite_bar_vertical_pressed")
|
||||
scrollbar.m_SpriteBarVerticalPressed = attr_value;
|
||||
else if (attr_name == "sprite_slider_vertical")
|
||||
scrollbar.m_SpriteSliderVertical = attr_value;
|
||||
else if (attr_name == "sprite_slider_vertical_over")
|
||||
scrollbar.m_SpriteSliderVerticalOver = attr_value;
|
||||
else if (attr_name == "sprite_slider_vertical_pressed")
|
||||
scrollbar.m_SpriteSliderVerticalPressed = attr_value;
|
||||
else if (attr_name == "sprite_back_horizontal")
|
||||
scrollbar.m_SpriteBackHorizontal = attr_value;
|
||||
else if (attr_name == "sprite_slider_horizontal")
|
||||
scrollbar.m_SpriteSliderHorizontal = attr_value;
|
||||
else if (attr_name == "sprite_slider_horizontal_over")
|
||||
scrollbar.m_SpriteSliderHorizontalOver = attr_value;
|
||||
else if (attr_name == "sprite_slider_horizontal_pressed")
|
||||
scrollbar.m_SpriteSliderHorizontalPressed = attr_value;
|
||||
}
|
||||
|
||||
m_ScrollBarStyles.erase(name);
|
||||
|
|
|
|||
|
|
@ -662,6 +662,8 @@ private:
|
|||
static const CStr EventNameMouseLeftPress;
|
||||
static const CStr EventNameMouseWheelDown;
|
||||
static const CStr EventNameMouseWheelUp;
|
||||
static const CStr EventNameMouseWheelLeft;
|
||||
static const CStr EventNameMouseWheelRight;
|
||||
static const CStr EventNameMouseLeftDoubleClick;
|
||||
static const CStr EventNameMouseLeftRelease;
|
||||
static const CStr EventNameMouseRightDoubleClick;
|
||||
|
|
|
|||
225
source/gui/CGUIScrollBarHorizontal.cpp
Normal file
225
source/gui/CGUIScrollBarHorizontal.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "CGUIScrollBarHorizontal.h"
|
||||
|
||||
#include "gui/CGUI.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
CGUIScrollBarHorizontal::CGUIScrollBarHorizontal(CGUI& pGUI)
|
||||
: IGUIScrollBar(pGUI)
|
||||
{
|
||||
}
|
||||
|
||||
CGUIScrollBarHorizontal::~CGUIScrollBarHorizontal()
|
||||
{
|
||||
}
|
||||
|
||||
void CGUIScrollBarHorizontal::SetPosFromMousePos(const CVector2D& mouse)
|
||||
{
|
||||
if (!GetStyle())
|
||||
return;
|
||||
|
||||
// Calculate the position for the top of the item being scrolled
|
||||
float emptyBackground = m_Length - m_BarSize;
|
||||
|
||||
if (GetStyle()->m_UseEdgeButtons)
|
||||
emptyBackground -= GetStyle()->m_Width * 2;
|
||||
|
||||
m_Pos = m_PosWhenPressed + GetMaxPos() * (mouse.X - m_BarPressedAtPos.X) / emptyBackground;
|
||||
}
|
||||
|
||||
void CGUIScrollBarHorizontal::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
if (!IsVisible())
|
||||
return;
|
||||
|
||||
if (!GetStyle())
|
||||
{
|
||||
LOGWARNING("Attempt to draw scrollbar without a style.");
|
||||
return;
|
||||
}
|
||||
|
||||
CRect outline = GetOuterRect();
|
||||
|
||||
m_pGUI.DrawSprite(
|
||||
GetStyle()->m_SpriteBackHorizontal,
|
||||
canvas,
|
||||
CRect(
|
||||
outline.left + (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Width : 0),
|
||||
outline.top,
|
||||
outline.right - (GetStyle()->m_UseEdgeButtons ? GetStyle()->m_Width : 0),
|
||||
outline.bottom));
|
||||
|
||||
if (GetStyle()->m_UseEdgeButtons)
|
||||
{
|
||||
const CGUISpriteInstance* button_left;
|
||||
const CGUISpriteInstance* button_right;
|
||||
|
||||
if (m_ButtonMinusHovered)
|
||||
{
|
||||
if (m_ButtonMinusPressed)
|
||||
button_left = &(GetStyle()->m_SpriteButtonLeftPressed ? GetStyle()->m_SpriteButtonLeftPressed : GetStyle()->m_SpriteButtonLeft);
|
||||
else
|
||||
button_left = &(GetStyle()->m_SpriteButtonLeftOver ? GetStyle()->m_SpriteButtonLeftOver : GetStyle()->m_SpriteButtonLeft);
|
||||
}
|
||||
else
|
||||
button_left = &GetStyle()->m_SpriteButtonLeft;
|
||||
|
||||
if (m_ButtonPlusHovered)
|
||||
{
|
||||
if (m_ButtonPlusPressed)
|
||||
button_right = &(GetStyle()->m_SpriteButtonRightPressed ? GetStyle()->m_SpriteButtonRightPressed : GetStyle()->m_SpriteButtonRight);
|
||||
else
|
||||
button_right = &(GetStyle()->m_SpriteButtonRightOver ? GetStyle()->m_SpriteButtonRightOver : GetStyle()->m_SpriteButtonRight);
|
||||
}
|
||||
else
|
||||
button_right = &GetStyle()->m_SpriteButtonRight;
|
||||
|
||||
m_pGUI.DrawSprite(
|
||||
*button_left,
|
||||
canvas,
|
||||
CRect(
|
||||
outline.left,
|
||||
outline.top,
|
||||
outline.left + GetStyle()->m_Width,
|
||||
outline.bottom));
|
||||
|
||||
m_pGUI.DrawSprite(
|
||||
*button_right,
|
||||
canvas,
|
||||
CRect(
|
||||
outline.right - GetStyle()->m_Width,
|
||||
outline.top,
|
||||
outline.right,
|
||||
outline.bottom));
|
||||
}
|
||||
|
||||
m_pGUI.DrawSprite(
|
||||
GetStyle()->m_SpriteSliderHorizontal,
|
||||
canvas,
|
||||
GetBarRect()
|
||||
);
|
||||
}
|
||||
|
||||
void CGUIScrollBarHorizontal::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
switch (Message.type)
|
||||
{
|
||||
case GUIM_MOUSE_WHEEL_LEFT:
|
||||
{
|
||||
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);
|
||||
Message.Skip(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case GUIM_MOUSE_WHEEL_RIGHT:
|
||||
{
|
||||
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);
|
||||
Message.Skip(false);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
IGUIScrollBar::HandleMessage(Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CRect CGUIScrollBarHorizontal::GetBarRect() const
|
||||
{
|
||||
CRect ret;
|
||||
if (!GetStyle())
|
||||
return ret;
|
||||
|
||||
// Get from where the scroll area begins to where it ends
|
||||
float from = m_X;
|
||||
float to = m_X + m_Length - m_BarSize;
|
||||
|
||||
if (GetStyle()->m_UseEdgeButtons)
|
||||
{
|
||||
from += GetStyle()->m_Width;
|
||||
to -= GetStyle()->m_Width;
|
||||
}
|
||||
|
||||
ret.left = from + (to - from) * m_Pos / GetMaxPos();
|
||||
ret.right = ret.left + m_BarSize;
|
||||
ret.bottom = m_Y + (m_BottomAligned ? 0 : GetStyle()->m_Width);
|
||||
ret.top = ret.bottom - GetStyle()->m_Width;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CRect CGUIScrollBarHorizontal::GetOuterRect() const
|
||||
{
|
||||
CRect ret;
|
||||
if (!GetStyle())
|
||||
return ret;
|
||||
|
||||
ret.left = m_X;
|
||||
ret.right = m_X + m_Length;
|
||||
ret.bottom = m_Y + (m_BottomAligned ? 0 : GetStyle()->m_Width);
|
||||
ret.top = ret.bottom - GetStyle()->m_Width;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CGUIScrollBarHorizontal::HoveringButtonMinus(const CVector2D& mouse)
|
||||
{
|
||||
if (!GetStyle())
|
||||
return false;
|
||||
|
||||
float StartY = m_BottomAligned ? m_Y - GetStyle()->m_Width : m_Y;
|
||||
|
||||
return mouse.Y >= StartY &&
|
||||
mouse.Y <= StartY + GetStyle()->m_Width &&
|
||||
mouse.X >= m_X &&
|
||||
mouse.X <= m_X + GetStyle()->m_Width;
|
||||
}
|
||||
|
||||
bool CGUIScrollBarHorizontal::HoveringButtonPlus(const CVector2D& mouse)
|
||||
{
|
||||
if (!GetStyle())
|
||||
return false;
|
||||
|
||||
float StartY = m_BottomAligned ? m_Y - GetStyle()->m_Width : m_Y;
|
||||
|
||||
return mouse.Y > StartY &&
|
||||
mouse.Y < StartY + GetStyle()->m_Width &&
|
||||
mouse.X > m_X + m_Length - GetStyle()->m_Width &&
|
||||
mouse.X < m_X + m_Length;
|
||||
}
|
||||
|
||||
void CGUIScrollBarHorizontal::SetScrollPlentyFromMousePos(const CVector2D& mouse)
|
||||
{
|
||||
// Scroll plus or minus a lot, this might change, it doesn't
|
||||
// have to be fancy though.
|
||||
if (mouse.X < GetBarRect().left)
|
||||
ScrollMinusPlenty();
|
||||
else
|
||||
ScrollPlusPlenty();
|
||||
}
|
||||
98
source/gui/CGUIScrollBarHorizontal.h
Normal file
98
source/gui/CGUIScrollBarHorizontal.h
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CGUISCROLLBARHORIZONTAL
|
||||
#define INCLUDED_CGUISCROLLBARHORIZONTAL
|
||||
|
||||
#include "IGUIScrollBar.h"
|
||||
|
||||
/**
|
||||
* Horizontal implementation of IGUIScrollBar
|
||||
*
|
||||
* @see IGUIScrollBar
|
||||
*/
|
||||
class CGUIScrollBarHorizontal : public IGUIScrollBar
|
||||
{
|
||||
public:
|
||||
CGUIScrollBarHorizontal(CGUI& pGUI);
|
||||
virtual ~CGUIScrollBarHorizontal();
|
||||
|
||||
/**
|
||||
* Draw the scroll-bar
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @see IGUIObject#HandleMessage()
|
||||
*/
|
||||
virtual void HandleMessage(SGUIMessage& Message);
|
||||
|
||||
/**
|
||||
* Set m_Pos with g_mouse_x/y input, i.e. when dragging.
|
||||
*/
|
||||
virtual void SetPosFromMousePos(const CVector2D& mouse);
|
||||
|
||||
virtual void SetScrollPlentyFromMousePos(const CVector2D& mouse);
|
||||
|
||||
/**
|
||||
* @see IGUIScrollBar#HoveringButtonMinus
|
||||
*/
|
||||
virtual bool HoveringButtonMinus(const CVector2D& mouse);
|
||||
|
||||
/**
|
||||
* @see IGUIScrollBar#HoveringButtonPlus
|
||||
*/
|
||||
virtual bool HoveringButtonPlus(const CVector2D& mouse);
|
||||
|
||||
/**
|
||||
* Set Right Aligned
|
||||
* @param align Alignment
|
||||
*/
|
||||
void SetBottomAligned(const bool& align) { m_BottomAligned = align; }
|
||||
|
||||
/**
|
||||
* Get the rectangle of the actual BAR.
|
||||
* @return Rectangle, CRect
|
||||
*/
|
||||
virtual CRect GetBarRect() const;
|
||||
|
||||
/**
|
||||
* Get the rectangle of the outline of the scrollbar, every component of the
|
||||
* scroll-bar should be inside this area.
|
||||
* @return Rectangle, CRect
|
||||
*/
|
||||
virtual CRect GetOuterRect() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Should the scroll bar proceed to the top or to the bottom of the m_Y value.
|
||||
* Notice, this has nothing to do with where the owner places it.
|
||||
*/
|
||||
bool m_BottomAligned;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_CGUISCROLLBARHORIZONTAL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -119,7 +119,7 @@ void CGUIScrollBarVertical::Draw(CCanvas2D& canvas)
|
|||
}
|
||||
|
||||
m_pGUI.DrawSprite(
|
||||
GetStyle()->m_SpriteBarVertical,
|
||||
GetStyle()->m_SpriteSliderVertical,
|
||||
canvas,
|
||||
GetBarRect()
|
||||
);
|
||||
|
|
@ -128,7 +128,34 @@ void CGUIScrollBarVertical::Draw(CCanvas2D& canvas)
|
|||
|
||||
void CGUIScrollBarVertical::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
IGUIScrollBar::HandleMessage(Message);
|
||||
switch (Message.type)
|
||||
{
|
||||
case GUIM_MOUSE_WHEEL_UP:
|
||||
{
|
||||
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);
|
||||
Message.Skip(false);
|
||||
break;
|
||||
}
|
||||
|
||||
case GUIM_MOUSE_WHEEL_DOWN:
|
||||
{
|
||||
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);
|
||||
Message.Skip(false);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
IGUIScrollBar::HandleMessage(Message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CRect CGUIScrollBarVertical::GetBarRect() const
|
||||
|
|
@ -194,3 +221,13 @@ bool CGUIScrollBarVertical::HoveringButtonPlus(const CVector2D& mouse)
|
|||
mouse.Y > m_Y + m_Length - GetStyle()->m_Width &&
|
||||
mouse.Y < m_Y + m_Length;
|
||||
}
|
||||
|
||||
void CGUIScrollBarVertical::SetScrollPlentyFromMousePos(const CVector2D& 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,8 @@ public:
|
|||
*/
|
||||
virtual void SetPosFromMousePos(const CVector2D& mouse);
|
||||
|
||||
virtual void SetScrollPlentyFromMousePos(const CVector2D& mouse);
|
||||
|
||||
/**
|
||||
* @see IGUIScrollBar#HoveringButtonMinus
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2023 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
#include "gui/SettingTypes/CGUISize.h"
|
||||
#include "gui/SettingTypes/CGUIString.h"
|
||||
#include "gui/SettingTypes/EAlign.h"
|
||||
#include "gui/SettingTypes/EScrollOrientation.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/CStr.h"
|
||||
#include "scriptinterface/ScriptConversions.h"
|
||||
|
|
@ -126,5 +127,6 @@ TYPE(EAlign)
|
|||
TYPE(EVAlign)
|
||||
TYPE(CGUIList)
|
||||
TYPE(CGUISeries)
|
||||
TYPE(EScrollOrientation)
|
||||
|
||||
#undef TYPE
|
||||
|
|
|
|||
75
source/gui/GUIObjectEventBroadcaster.h
Normal file
75
source/gui/GUIObjectEventBroadcaster.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#ifndef GUIOBJECTEVENTBROADCASTER
|
||||
#define GUIOBJECTEVENTBROADCASTER
|
||||
|
||||
#include "gui/ObjectBases/IGUIObject.h"
|
||||
#include "gui/ObjectBases/IGUIPanel.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct VisibleObject
|
||||
{
|
||||
IGUIObject* object;
|
||||
// Index of the object in a depth-first search inside GUI tree.
|
||||
u32 index;
|
||||
// Cached value of GetBufferedZ to avoid recursive calls in a deep hierarchy.
|
||||
float bufferedZ;
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
void CollectVisibleObjectsRecursively(const std::vector<IGUIObject*>& objects, Container* visibleObjects)
|
||||
{
|
||||
for (IGUIObject* const& object : objects)
|
||||
if (!object->IsHidden())
|
||||
{
|
||||
visibleObjects->emplace_back(VisibleObject{ object, static_cast<u32>(visibleObjects->size()), 0.0f });
|
||||
CollectVisibleObjectsRecursively(object->GetVisibleChildren(), visibleObjects);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CGUIObjectEventBroadcaster
|
||||
{
|
||||
public:
|
||||
template<typename... Args>
|
||||
static void RecurseVisibleObject(IGUIObject* object, void(IGUIObject::* callbackFunction)(Args... args), Args&&... args)
|
||||
{
|
||||
using Arena = Allocators::DynamicArena<128 * KiB>;
|
||||
using ObjectListAllocator = ProxyAllocator<VisibleObject, Arena>;
|
||||
Arena arena;
|
||||
|
||||
std::vector<VisibleObject, ObjectListAllocator> visibleObjects((ObjectListAllocator(arena)));
|
||||
CollectVisibleObjectsRecursively(object->GetVisibleChildren(), &visibleObjects);
|
||||
for (VisibleObject& visibleObject : visibleObjects)
|
||||
visibleObject.bufferedZ = visibleObject.object->GetBufferedZ();
|
||||
|
||||
std::sort(visibleObjects.begin(), visibleObjects.end(), [](const VisibleObject& visibleObject1, const VisibleObject& visibleObject2) -> bool {
|
||||
if (visibleObject1.bufferedZ != visibleObject2.bufferedZ)
|
||||
return visibleObject1.bufferedZ < visibleObject2.bufferedZ;
|
||||
return visibleObject1.index < visibleObject2.index;
|
||||
});
|
||||
|
||||
for (const VisibleObject& visibleObject : visibleObjects)
|
||||
(visibleObject.object->*callbackFunction)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // !GUIOBJECTEVENTBROADCASTER
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
#include "gui/ObjectTypes/CProgressBar.h"
|
||||
#include "gui/ObjectTypes/CRadioButton.h"
|
||||
#include "gui/ObjectTypes/CSlider.h"
|
||||
#include "gui/ObjectTypes/CScrollPanel.h"
|
||||
#include "gui/ObjectTypes/CText.h"
|
||||
#include "gui/ObjectTypes/CTooltip.h"
|
||||
#include "gui/Scripting/JSInterface_GUIProxy.h"
|
||||
|
|
@ -42,6 +43,7 @@ void CGUI::AddObjectTypes()
|
|||
m_ProxyData.insert(JSI_GUIProxy<CList>::CreateData(*m_ScriptInterface));
|
||||
m_ProxyData.insert(JSI_GUIProxy<CMiniMap>::CreateData(*m_ScriptInterface));
|
||||
m_ProxyData.insert(JSI_GUIProxy<CButton>::CreateData(*m_ScriptInterface));
|
||||
m_ProxyData.insert(JSI_GUIProxy<CScrollPanel>::CreateData(*m_ScriptInterface));
|
||||
|
||||
AddObjectType("button", &CButton::ConstructObject);
|
||||
AddObjectType("chart", &CChart::ConstructObject);
|
||||
|
|
@ -59,4 +61,5 @@ void CGUI::AddObjectTypes()
|
|||
AddObjectType("slider", &CSlider::ConstructObject);
|
||||
AddObjectType("text", &CText::ConstructObject);
|
||||
AddObjectType("tooltip", &CTooltip::ConstructObject);
|
||||
AddObjectType("scrollpanel", &CScrollPanel::ConstructObject);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "precompiled.h"
|
||||
|
||||
#include "gui/CGUI.h"
|
||||
#include "gui/SettingTypes/EScrollOrientation.h"
|
||||
#include "gui/SettingTypes/CGUIString.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
|
|
@ -244,3 +245,18 @@ bool CGUI::ParseString<CGUIList>(const CGUI* UNUSED(pGUI), const CStrW& UNUSED(V
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool CGUI::ParseString<EScrollOrientation>(const CGUI* UNUSED(pGUI), const CStrW& Value, EScrollOrientation& Output)
|
||||
{
|
||||
if (Value == L"vertical")
|
||||
Output = EScrollOrientation::VERTICAL;
|
||||
else if (Value == L"horizontal")
|
||||
Output = EScrollOrientation::HORIZONTAL;
|
||||
else if (Value == L"both")
|
||||
Output = EScrollOrientation::BOTH;
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -147,12 +147,8 @@ void IGUIScrollBar::HandleMessage(SGUIMessage& Message)
|
|||
{
|
||||
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();
|
||||
SetScrollPlentyFromMousePos(mouse);
|
||||
|
||||
// Simulate mouse movement to see if bar now is hovered
|
||||
SGUIMessage msg(GUIM_MOUSE_MOTION);
|
||||
HandleMessage(msg);
|
||||
|
|
@ -165,27 +161,6 @@ void IGUIScrollBar::HandleMessage(SGUIMessage& Message)
|
|||
m_ButtonMinusPressed = false;
|
||||
m_ButtonPlusPressed = false;
|
||||
break;
|
||||
|
||||
case GUIM_MOUSE_WHEEL_UP:
|
||||
{
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
case GUIM_MOUSE_WHEEL_DOWN:
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -111,9 +111,9 @@ struct SGUIScrollBarStyle
|
|||
CGUISpriteInstance m_SpriteButtonBottomDisabled;
|
||||
CGUISpriteInstance m_SpriteButtonBottomOver;
|
||||
|
||||
CGUISpriteInstance m_SpriteBarVertical;
|
||||
CGUISpriteInstance m_SpriteBarVerticalOver;
|
||||
CGUISpriteInstance m_SpriteBarVerticalPressed;
|
||||
CGUISpriteInstance m_SpriteSliderVertical;
|
||||
CGUISpriteInstance m_SpriteSliderVerticalOver;
|
||||
CGUISpriteInstance m_SpriteSliderVerticalPressed;
|
||||
|
||||
CGUISpriteInstance m_SpriteBackVertical;
|
||||
|
||||
|
|
@ -126,13 +126,17 @@ struct SGUIScrollBarStyle
|
|||
CGUISpriteInstance m_SpriteButtonLeft;
|
||||
CGUISpriteInstance m_SpriteButtonLeftPressed;
|
||||
CGUISpriteInstance m_SpriteButtonLeftDisabled;
|
||||
CGUISpriteInstance m_SpriteButtonLeftOver;
|
||||
|
||||
CGUISpriteInstance m_SpriteButtonRight;
|
||||
CGUISpriteInstance m_SpriteButtonRightPressed;
|
||||
CGUISpriteInstance m_SpriteButtonRightDisabled;
|
||||
CGUISpriteInstance m_SpriteButtonRightOver;
|
||||
|
||||
CGUISpriteInstance m_SpriteBackHorizontal;
|
||||
CGUISpriteInstance m_SpriteBarHorizontal;
|
||||
CGUISpriteInstance m_SpriteSliderHorizontal;
|
||||
CGUISpriteInstance m_SpriteSliderHorizontalOver;
|
||||
CGUISpriteInstance m_SpriteSliderHorizontalPressed;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
|
@ -179,6 +183,8 @@ public:
|
|||
*/
|
||||
virtual void SetPosFromMousePos(const CVector2D& mouse) = 0;
|
||||
|
||||
virtual void SetScrollPlentyFromMousePos(const CVector2D& mouse) = 0;
|
||||
|
||||
/**
|
||||
* Hovering the scroll minus button
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
|
||||
const CStr IGUIObject::EventNameMouseEnter = "MouseEnter";
|
||||
const CStr IGUIObject::EventNameMouseMove = "MouseMove";
|
||||
const CStr IGUIObject::EventNameMouseLeave = "MouseLeave";
|
||||
|
|
@ -135,11 +136,34 @@ void IGUIObject::SettingChanged(const CStr& Setting, const bool SendMessage)
|
|||
{
|
||||
SGUIMessage msg(GUIM_SETTINGS_UPDATED, Setting);
|
||||
HandleMessage(msg);
|
||||
|
||||
// inform to parents until get to the root object
|
||||
// for now only size and hidden settings are bubbled up
|
||||
if (GetParent() && (Setting == "size" || Setting == "hidden"))
|
||||
{
|
||||
EGUIMessageType type = Setting == "size" ? GUIM_CHILD_RESIZED : GUIM_CHILD_TOGGLE_VISIBILITY;
|
||||
SGUIMessage msg(type, GetName());
|
||||
msg.Skip(true);
|
||||
|
||||
IGUIObject* parent = GetParent();
|
||||
while (parent)
|
||||
{
|
||||
parent->HandleMessage(msg);
|
||||
|
||||
if (!msg.skipped)
|
||||
break;
|
||||
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IGUIObject::IsMouseOver() const
|
||||
{
|
||||
if (m_VisibleArea)
|
||||
return m_VisibleArea.PointInside(m_pGUI.GetMousePos());
|
||||
|
||||
return m_CachedActualSize.PointInside(m_pGUI.GetMousePos());
|
||||
}
|
||||
|
||||
|
|
@ -236,7 +260,6 @@ CRect IGUIObject::GetComputedSize()
|
|||
return m_CachedActualSize;
|
||||
}
|
||||
|
||||
|
||||
bool IGUIObject::ApplyStyle(const CStr& StyleName)
|
||||
{
|
||||
if (!m_pGUI.HasStyle(StyleName))
|
||||
|
|
@ -362,6 +385,8 @@ InReaction IGUIObject::SendMouseEvent(EGUIMessageType type, const CStr& eventNam
|
|||
PROFILE2_ATTR("object: %s", m_Name.c_str());
|
||||
|
||||
SGUIMessage msg(type);
|
||||
if (type == GUIM_MOUSE_WHEEL_UP || type == GUIM_MOUSE_WHEEL_DOWN || type == GUIM_MOUSE_WHEEL_LEFT || type == GUIM_MOUSE_WHEEL_RIGHT)
|
||||
msg.Skip(true);
|
||||
HandleMessage(msg);
|
||||
|
||||
ScriptRequest rq(m_pGUI.GetScriptInterface());
|
||||
|
|
@ -381,6 +406,11 @@ InReaction IGUIObject::SendMouseEvent(EGUIMessageType type, const CStr& eventNam
|
|||
ignore_result(paramData.append(mouse));
|
||||
ScriptEvent(eventName, paramData);
|
||||
|
||||
// inform to parents until get to the root object
|
||||
// for now only wheel events are bubbled up
|
||||
if (GetParent() && (type == GUIM_MOUSE_WHEEL_UP || type == GUIM_MOUSE_WHEEL_DOWN || type == GUIM_MOUSE_WHEEL_LEFT || type == GUIM_MOUSE_WHEEL_RIGHT) && msg.skipped)
|
||||
msg.Skip(GetParent()->SendMouseEvent(type, eventName) == IN_PASS);
|
||||
|
||||
return msg.skipped ? IN_PASS : IN_HANDLED;
|
||||
}
|
||||
|
||||
|
|
@ -500,3 +530,24 @@ void IGUIObject::TraceMember(JSTracer* trc)
|
|||
for (std::pair<const CStr, JS::Heap<JSObject*>>& handler : m_ScriptHandlers)
|
||||
JS::TraceEdge(trc, &handler.second, "IGUIObject::m_ScriptHandlers");
|
||||
}
|
||||
|
||||
void IGUIObject::DrawInArea(CCanvas2D& canvas, CRect& area)
|
||||
{
|
||||
bool isInsideBoundaries = false;
|
||||
RecurseObject(nullptr, &IGUIObject::SetIsInsideBoundaries, isInsideBoundaries);
|
||||
if (!area.IntersectWith(m_CachedActualSize))
|
||||
return;
|
||||
|
||||
CRect intersection = area.Intersection(m_CachedActualSize);
|
||||
|
||||
m_VisibleArea = intersection;
|
||||
|
||||
Draw(canvas);
|
||||
|
||||
isInsideBoundaries = true;
|
||||
RecurseObject(nullptr, &IGUIObject::SetIsInsideBoundaries, isInsideBoundaries);
|
||||
}
|
||||
|
||||
bool IGUIObject::IsHiddenOrGhostOrOutOfBoundaries() const {
|
||||
return !m_IsInsideBoundaries || IsHiddenOrGhost();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -29,6 +29,8 @@
|
|||
#include "gui/SettingTypes/CGUIHotkey.h"
|
||||
#include "gui/SettingTypes/CGUISize.h"
|
||||
#include "gui/SGUIMessage.h"
|
||||
#include "lib/allocators/DynamicArena.h"
|
||||
#include "lib/allocators/STLAllocators.h"
|
||||
#include "lib/input.h" // just for IN_PASS
|
||||
#include "ps/CStr.h"
|
||||
#include "ps/XML/Xeromyces.h"
|
||||
|
|
@ -40,6 +42,7 @@
|
|||
class CCanvas2D;
|
||||
class CGUI;
|
||||
class CGUISize;
|
||||
class CGUIObjectEventBroadcaster;
|
||||
class IGUIObject;
|
||||
class IGUIProxyObject;
|
||||
class IGUISetting;
|
||||
|
|
@ -59,6 +62,7 @@ public: \
|
|||
class IGUIObject
|
||||
{
|
||||
friend class CGUI;
|
||||
friend class CGUIObjectEventBroadcaster;
|
||||
|
||||
// For triggering message update handlers.
|
||||
friend class IGUISetting;
|
||||
|
|
@ -189,7 +193,7 @@ public:
|
|||
/**
|
||||
* Updates and returns the size of the object.
|
||||
*/
|
||||
CRect GetComputedSize();
|
||||
virtual CRect GetComputedSize();
|
||||
|
||||
virtual const CStrW& GetTooltipText() const { return m_Tooltip; }
|
||||
virtual const CStr& GetTooltipStyle() const { return m_TooltipStyle; }
|
||||
|
|
@ -213,6 +217,10 @@ public:
|
|||
*/
|
||||
JSObject* GetJSObject();
|
||||
|
||||
virtual const std::vector<IGUIObject*>& GetVisibleChildren() const { return m_Children; }
|
||||
void SetIsInsideBoundaries(bool& isInsideBoundaries) { m_IsInsideBoundaries = isInsideBoundaries; }
|
||||
bool IsHiddenOrGhostOrOutOfBoundaries() const;
|
||||
|
||||
//@}
|
||||
protected:
|
||||
//--------------------------------------------------------
|
||||
|
|
@ -261,6 +269,8 @@ public:
|
|||
obj->RecurseObject(isRestricted, callbackFunction, args...);
|
||||
}
|
||||
|
||||
virtual void DrawInArea(CCanvas2D& canvas, CRect& area);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Draws the object.
|
||||
|
|
@ -525,6 +535,9 @@ protected:
|
|||
// Cached JSObject representing this GUI object.
|
||||
std::unique_ptr<IGUIProxyObject> m_JSObject;
|
||||
|
||||
CRect m_VisibleArea;
|
||||
bool m_IsInsideBoundaries = true;
|
||||
|
||||
CGUISimpleSetting<bool> m_Enabled;
|
||||
CGUISimpleSetting<bool> m_Hidden;
|
||||
CGUISimpleSetting<CGUISize> m_Size;
|
||||
|
|
|
|||
57
source/gui/ObjectBases/IGUIPanel.cpp
Normal file
57
source/gui/ObjectBases/IGUIPanel.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* Copyright (C) 20244 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "IGUIPanel.h"
|
||||
|
||||
#include "gui/CGUI.h"
|
||||
|
||||
IGUIPanel::IGUIPanel(CGUI& pGUI)
|
||||
: IGUIObject(pGUI)
|
||||
{
|
||||
}
|
||||
|
||||
IGUIPanel::~IGUIPanel()
|
||||
{
|
||||
}
|
||||
|
||||
bool IGUIPanel::IsMouseOver() const
|
||||
{
|
||||
return m_CachedLayoutActualSize.PointInside(m_pGUI.GetMousePos());
|
||||
}
|
||||
|
||||
void IGUIPanel::UpdateCachedSize()
|
||||
{
|
||||
IGUIObject::UpdateCachedSize();
|
||||
m_CachedLayoutActualSize = m_CachedActualSize;
|
||||
}
|
||||
|
||||
CRect IGUIPanel::GetComputedSize()
|
||||
{
|
||||
UpdateCachedSize();
|
||||
return m_CachedLayoutActualSize;
|
||||
}
|
||||
|
||||
const std::vector<IGUIObject*>& IGUIPanel::GetVisibleChildren() const
|
||||
{
|
||||
if (m_Drawing)
|
||||
return m_Children;
|
||||
|
||||
static std::vector<IGUIObject*> emptyVector;
|
||||
return emptyVector;
|
||||
}
|
||||
41
source/gui/ObjectBases/IGUIPanel.h
Normal file
41
source/gui/ObjectBases/IGUIPanel.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* Copyright (C) 20244 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_IPANEL
|
||||
#define INCLUDED_IPANEL
|
||||
|
||||
#include "gui/ObjectBases/IGUIObject.h"
|
||||
|
||||
class IGUIPanel : public IGUIObject
|
||||
{
|
||||
public:
|
||||
IGUIPanel(CGUI& pGUI);
|
||||
virtual ~IGUIPanel();
|
||||
|
||||
virtual void UpdateCachedSize();
|
||||
virtual CRect GetComputedSize();
|
||||
|
||||
virtual bool IsMouseOver() const;
|
||||
|
||||
virtual const std::vector<IGUIObject*>& GetVisibleChildren() const;
|
||||
|
||||
protected:
|
||||
CRect m_CachedLayoutActualSize;
|
||||
bool m_Drawing = false;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_IPANEL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -50,7 +50,8 @@ const SGUIScrollBarStyle* IGUIScrollBarOwner::GetScrollBarStyle(const CStr& styl
|
|||
void IGUIScrollBarOwner::HandleMessage(SGUIMessage& msg)
|
||||
{
|
||||
for (const std::unique_ptr<IGUIScrollBar>& scrollBar : m_ScrollBars)
|
||||
scrollBar->HandleMessage(msg);
|
||||
if (scrollBar->IsVisible())
|
||||
scrollBar->HandleMessage(msg);
|
||||
}
|
||||
|
||||
void IGUIScrollBarOwner::Draw(CCanvas2D& canvas)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -85,9 +85,10 @@ void CButton::Draw(CCanvas2D& canvas)
|
|||
m_pGUI.DrawSprite(
|
||||
GetButtonSprite(m_Sprite, m_SpriteOver, m_SpritePressed, m_SpriteDisabled),
|
||||
canvas,
|
||||
m_CachedActualSize);
|
||||
m_CachedActualSize,
|
||||
m_VisibleArea);
|
||||
|
||||
DrawText(canvas, 0, ChooseColor(), m_TextPos);
|
||||
DrawText(canvas, 0, ChooseColor(), m_TextPos, m_VisibleArea);
|
||||
}
|
||||
|
||||
bool CButton::IsMouseOver() const
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "ps/Profile.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
|
||||
CChart::CChart(CGUI& pGUI)
|
||||
: IGUIObject(pGUI),
|
||||
|
|
@ -80,6 +81,10 @@ void CChart::Draw(CCanvas2D& canvas)
|
|||
if (m_Series.empty())
|
||||
return;
|
||||
|
||||
std::optional<CCanvas2D::ScopedScissor> scissor;
|
||||
if (m_VisibleArea)
|
||||
scissor.emplace(canvas, m_VisibleArea);
|
||||
|
||||
CRect rect = GetChartRect();
|
||||
const float width = rect.GetWidth();
|
||||
const float height = rect.GetHeight();
|
||||
|
|
@ -90,7 +95,7 @@ void CChart::Draw(CCanvas2D& canvas)
|
|||
{
|
||||
if (data.m_Points.empty())
|
||||
continue;
|
||||
|
||||
|
||||
linePoints.clear();
|
||||
for (const CVector2D& point : data.m_Points)
|
||||
{
|
||||
|
|
@ -114,7 +119,7 @@ void CChart::Draw(CCanvas2D& canvas)
|
|||
DrawAxes(canvas);
|
||||
|
||||
for (size_t i = 0; i < m_TextPositions.size(); ++i)
|
||||
DrawText(canvas, i, CGUIColor(1.f, 1.f, 1.f, 1.f), m_TextPositions[i]);
|
||||
DrawText(canvas, i, CGUIColor(1.f, 1.f, 1.f, 1.f), m_TextPositions[i], m_VisibleArea);
|
||||
}
|
||||
|
||||
CRect CChart::GetChartRect() const
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -71,5 +71,6 @@ void CCheckBox::Draw(CCanvas2D& canvas)
|
|||
GetButtonSprite(m_SpriteChecked, m_SpriteCheckedOver, m_SpriteCheckedPressed, m_SpriteCheckedDisabled) :
|
||||
GetButtonSprite(m_SpriteUnchecked, m_SpriteUncheckedOver, m_SpriteUncheckedPressed, m_SpriteUncheckedDisabled),
|
||||
canvas,
|
||||
m_CachedActualSize);
|
||||
m_CachedActualSize,
|
||||
m_VisibleArea);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2023 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -164,6 +164,9 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
|
|||
if (m_List->m_Items.empty())
|
||||
return;
|
||||
|
||||
if (m_VisibleArea && !m_VisibleArea.PointInside(m_pGUI.GetMousePos()))
|
||||
return;
|
||||
|
||||
m_Open = true;
|
||||
GetScrollBar(0).SetZ(GetBufferedZ());
|
||||
m_ElementHighlight = m_Selected;
|
||||
|
|
@ -208,6 +211,8 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
|
|||
if (m_Open || !m_Enabled)
|
||||
break;
|
||||
|
||||
Message.Skip(false);
|
||||
|
||||
m_ElementHighlight = m_Selected;
|
||||
|
||||
if (m_ElementHighlight + 1 >= (int)m_ItemsYPositions.size() - 1)
|
||||
|
|
@ -224,6 +229,8 @@ void CDropDown::HandleMessage(SGUIMessage& Message)
|
|||
if (m_Open || !m_Enabled)
|
||||
break;
|
||||
|
||||
Message.Skip(false);
|
||||
|
||||
m_ElementHighlight = m_Selected;
|
||||
if (m_ElementHighlight - 1 < 0)
|
||||
break;
|
||||
|
|
@ -420,7 +427,7 @@ bool CDropDown::IsMouseOver() const
|
|||
return rect.PointInside(m_pGUI.GetMousePos());
|
||||
}
|
||||
else
|
||||
return m_CachedActualSize.PointInside(m_pGUI.GetMousePos());
|
||||
return IGUIObject::IsMouseOver();
|
||||
}
|
||||
|
||||
void CDropDown::Draw(CCanvas2D& canvas)
|
||||
|
|
@ -428,7 +435,7 @@ void CDropDown::Draw(CCanvas2D& canvas)
|
|||
const CGUISpriteInstance& sprite = m_Enabled ? m_Sprite : m_SpriteDisabled;
|
||||
const CGUISpriteInstance& spriteOverlay = m_Enabled ? m_SpriteOverlay : m_SpriteOverlayDisabled;
|
||||
|
||||
m_pGUI.DrawSprite(sprite, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(sprite, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
|
||||
if (m_ButtonWidth > 0.f)
|
||||
{
|
||||
|
|
@ -437,24 +444,25 @@ void CDropDown::Draw(CCanvas2D& canvas)
|
|||
|
||||
if (!m_Enabled)
|
||||
{
|
||||
m_pGUI.DrawSprite(*m_Sprite2Disabled ? m_Sprite2Disabled : m_Sprite2, canvas, rect);
|
||||
m_pGUI.DrawSprite(*m_Sprite2Disabled ? m_Sprite2Disabled : m_Sprite2, canvas, rect, m_VisibleArea);
|
||||
}
|
||||
else if (m_Open)
|
||||
{
|
||||
m_pGUI.DrawSprite(*m_Sprite2Pressed ? m_Sprite2Pressed : m_Sprite2, canvas, rect);
|
||||
m_pGUI.DrawSprite(*m_Sprite2Pressed ? m_Sprite2Pressed : m_Sprite2, canvas, rect, m_VisibleArea);
|
||||
}
|
||||
else if (m_MouseHovering)
|
||||
{
|
||||
m_pGUI.DrawSprite(*m_Sprite2Over ? m_Sprite2Over : m_Sprite2, canvas, rect);
|
||||
m_pGUI.DrawSprite(*m_Sprite2Over ? m_Sprite2Over : m_Sprite2, canvas, rect, m_VisibleArea);
|
||||
}
|
||||
else
|
||||
m_pGUI.DrawSprite(m_Sprite2, canvas, rect);
|
||||
m_pGUI.DrawSprite(m_Sprite2, canvas, rect, m_VisibleArea);
|
||||
}
|
||||
|
||||
if (m_Selected != -1) // TODO: Maybe check validity completely?
|
||||
{
|
||||
CRect cliparea(m_CachedActualSize.left, m_CachedActualSize.top,
|
||||
m_CachedActualSize.right - m_ButtonWidth, m_CachedActualSize.bottom);
|
||||
CRect cliparea = m_VisibleArea != CRect() ? m_VisibleArea : m_CachedActualSize;
|
||||
if (cliparea.right > m_CachedActualSize.right - m_ButtonWidth)
|
||||
cliparea.right = m_CachedActualSize.right - m_ButtonWidth;
|
||||
|
||||
CVector2D pos(m_CachedActualSize.left, m_CachedActualSize.top);
|
||||
DrawText(canvas, m_Selected, m_Enabled ? m_TextColorSelected : m_TextColorDisabled, pos, cliparea);
|
||||
|
|
@ -474,7 +482,7 @@ void CDropDown::Draw(CCanvas2D& canvas)
|
|||
if (m_HideScrollBar)
|
||||
m_ScrollBar.Set(old, false);
|
||||
}
|
||||
m_pGUI.DrawSprite(spriteOverlay, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(spriteOverlay, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
}
|
||||
|
||||
// When a dropdown list is opened, it needs to be visible above all the other
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -33,5 +33,5 @@ CImage::~CImage()
|
|||
|
||||
void CImage::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
m_pGUI.DrawSprite(m_Sprite, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(m_Sprite, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -883,7 +883,8 @@ void CInput::ResetStates()
|
|||
void CInput::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
IGUIObject::HandleMessage(Message);
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
if (m_ScrollBar)
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
|
||||
// Cleans up operator[] usage.
|
||||
const CStrW& caption = *m_Caption;
|
||||
|
|
@ -1486,7 +1487,7 @@ void CInput::DrawContent(CCanvas2D& canvas)
|
|||
void CInput::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
// We'll have to setup clipping manually, since we're doing the rendering manually.
|
||||
CRect cliparea(m_CachedActualSize);
|
||||
CRect cliparea = m_VisibleArea ? m_VisibleArea : m_CachedActualSize;
|
||||
|
||||
// First we'll figure out the clipping area, which is the cached actual size
|
||||
// substracted by an optional scrollbar
|
||||
|
|
@ -1521,7 +1522,7 @@ void CInput::Draw(CCanvas2D& canvas)
|
|||
IGUIScrollBarOwner::Draw(canvas);
|
||||
|
||||
// Draw the overlays last
|
||||
m_pGUI.DrawSprite(m_SpriteOverlay, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(m_SpriteOverlay, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
}
|
||||
|
||||
void CInput::DrawPlaceholderText(CCanvas2D& canvas, const CRect& clipping)
|
||||
|
|
|
|||
|
|
@ -155,7 +155,8 @@ void CList::UpdateCachedSize()
|
|||
void CList::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
IGUIObject::HandleMessage(Message);
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
if (m_ScrollBar)
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
//IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
|
||||
|
||||
m_Modified = false;
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ void COList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteIn
|
|||
{
|
||||
CRect rect = GetListRect();
|
||||
|
||||
m_pGUI.DrawSprite(sprite, canvas, rect);
|
||||
m_pGUI.DrawSprite(sprite, canvas, rect, m_VisibleArea);
|
||||
|
||||
float scroll = 0.f;
|
||||
if (m_ScrollBar)
|
||||
|
|
@ -341,7 +341,7 @@ void COList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteIn
|
|||
}
|
||||
|
||||
// Draw item selection
|
||||
m_pGUI.DrawSprite(spriteSelectArea, canvas, rectSel);
|
||||
m_pGUI.DrawSprite(spriteSelectArea, canvas, rectSel, m_VisibleArea);
|
||||
drawSelected = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -349,7 +349,7 @@ void COList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteIn
|
|||
// Draw line above column header
|
||||
CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right,
|
||||
m_CachedActualSize.top + m_HeadingHeight);
|
||||
m_pGUI.DrawSprite(m_SpriteHeading, canvas, rect_head);
|
||||
m_pGUI.DrawSprite(m_SpriteHeading, canvas, rect_head, m_VisibleArea);
|
||||
|
||||
// Draw column headers
|
||||
float xpos = 0;
|
||||
|
|
@ -386,7 +386,7 @@ void COList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteIn
|
|||
else
|
||||
pSprite = &*m_SpriteNotSorted;
|
||||
|
||||
m_pGUI.DrawSprite(*pSprite, canvas, CRect(leftTopCorner + CVector2D(width - SORT_SPRITE_DIM, 0), leftTopCorner + CVector2D(width, SORT_SPRITE_DIM)));
|
||||
m_pGUI.DrawSprite(*pSprite, canvas, CRect(leftTopCorner + CVector2D(width - SORT_SPRITE_DIM, 0), leftTopCorner + CVector2D(width, SORT_SPRITE_DIM)), m_VisibleArea);
|
||||
}
|
||||
|
||||
// Draw column header text
|
||||
|
|
@ -453,7 +453,7 @@ void COList::DrawList(CCanvas2D& canvas, const int& selected, const CGUISpriteIn
|
|||
IGUIScrollBarOwner::Draw(canvas);
|
||||
|
||||
// Draw the overlays last
|
||||
m_pGUI.DrawSprite(spriteOverlay, canvas, rect);
|
||||
m_pGUI.DrawSprite(spriteOverlay, canvas, rect, m_VisibleArea);
|
||||
if (drawSelected)
|
||||
m_pGUI.DrawSprite(spriteSelectAreaOverlay, canvas, rectSel);
|
||||
m_pGUI.DrawSprite(spriteSelectAreaOverlay, canvas, rectSel, m_VisibleArea);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -55,10 +55,10 @@ void CProgressBar::HandleMessage(SGUIMessage& Message)
|
|||
|
||||
void CProgressBar::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
m_pGUI.DrawSprite(m_SpriteBackground, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(m_SpriteBackground, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
|
||||
// Get size of bar (notice it is drawn slightly closer, to appear above the background)
|
||||
CRect size = m_CachedActualSize;
|
||||
size.right = size.left + m_CachedActualSize.GetWidth() * (m_Progress / 100.f),
|
||||
m_pGUI.DrawSprite(m_SpriteBar, canvas, size);
|
||||
m_pGUI.DrawSprite(m_SpriteBar, canvas, size, m_VisibleArea);
|
||||
}
|
||||
|
|
|
|||
257
source/gui/ObjectTypes/CScrollPanel.cpp
Normal file
257
source/gui/ObjectTypes/CScrollPanel.cpp
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "CScrollPanel.h"
|
||||
|
||||
#include "gui/GUIObjectEventBroadcaster.h"
|
||||
|
||||
#include "gui/CGUIScrollBarHorizontal.h"
|
||||
#include "gui/CGUIScrollBarVertical.h"
|
||||
|
||||
CScrollPanel::CScrollPanel(CGUI& pGUI)
|
||||
: IGUIPanel(pGUI),
|
||||
IGUIScrollBarOwner(*static_cast<IGUIObject*>(this)),
|
||||
m_Orientation(this, "orientation", EScrollOrientation::VERTICAL),
|
||||
m_ScrollBarStyle(this, "scrollbar_style"),
|
||||
m_MinWidth(this, "min_width", 0),
|
||||
m_MinHeight(this, "min_height", 0)
|
||||
{
|
||||
auto vbar = std::make_unique<CGUIScrollBarVertical>(pGUI);
|
||||
vbar->SetRightAligned(true);
|
||||
AddScrollBar(std::move(vbar));
|
||||
|
||||
auto hbar = std::make_unique<CGUIScrollBarHorizontal>(pGUI);
|
||||
hbar->SetBottomAligned(true);
|
||||
AddScrollBar(std::move(hbar));
|
||||
}
|
||||
|
||||
CScrollPanel::~CScrollPanel()
|
||||
{
|
||||
}
|
||||
|
||||
void CScrollPanel::ResetStates()
|
||||
{
|
||||
IGUIPanel::ResetStates();
|
||||
IGUIScrollBarOwner::ResetStates();
|
||||
}
|
||||
|
||||
void CScrollPanel::UpdateCachedSize()
|
||||
{
|
||||
IGUIPanel::UpdateCachedSize();
|
||||
Setup();
|
||||
}
|
||||
|
||||
void CScrollPanel::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
IGUIScrollBar& scrollbar0 = GetScrollBar(0);
|
||||
IGUIScrollBar& scrollbar1 = GetScrollBar(1);
|
||||
|
||||
IGUIPanel::HandleMessage(Message);
|
||||
|
||||
float vscroll = scrollbar0.GetPos();
|
||||
float hscroll = scrollbar1.GetPos();
|
||||
bool updateScrollPosition = false;
|
||||
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
|
||||
if (vscroll != scrollbar0.GetPos())
|
||||
{
|
||||
vscroll = scrollbar0.GetPos();
|
||||
updateScrollPosition = true;
|
||||
}
|
||||
|
||||
if (hscroll != scrollbar1.GetPos())
|
||||
{
|
||||
hscroll = scrollbar1.GetPos();
|
||||
updateScrollPosition = true;
|
||||
}
|
||||
|
||||
if (updateScrollPosition)
|
||||
UpdateScrollPosition(vscroll, hscroll);
|
||||
|
||||
switch (Message.type)
|
||||
{
|
||||
case GUIM_SETTINGS_UPDATED:
|
||||
if (Message.value == "scrollbar_style")
|
||||
{
|
||||
scrollbar0.SetScrollBarStyle(m_ScrollBarStyle);
|
||||
scrollbar1.SetScrollBarStyle(m_ScrollBarStyle);
|
||||
Setup();
|
||||
}
|
||||
|
||||
if (Message.value == "orientation" || Message.value == "size" || Message.value == "min_width" || Message.value == "min_height")
|
||||
{
|
||||
scrollbar0.SetPos(0);
|
||||
scrollbar1.SetPos(0);
|
||||
Setup();
|
||||
}
|
||||
break;
|
||||
|
||||
case GUIM_CHILD_RESIZED:
|
||||
case GUIM_CHILD_TOGGLE_VISIBILITY:
|
||||
Setup();
|
||||
Message.Skip(false);
|
||||
break;
|
||||
|
||||
case GUIM_LOAD:
|
||||
scrollbar0.SetScrollBarStyle(m_ScrollBarStyle);
|
||||
scrollbar1.SetScrollBarStyle(m_ScrollBarStyle);
|
||||
|
||||
Setup();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CScrollPanel::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
IGUIScrollBar& scrollbar0 = GetScrollBar(0);
|
||||
IGUIScrollBar& scrollbar1 = GetScrollBar(1);
|
||||
|
||||
m_Drawing = true;
|
||||
IGUIScrollBarOwner::Draw(canvas);
|
||||
|
||||
CRect cliparea(m_CachedLayoutActualSize);
|
||||
|
||||
// substract scrollbar from cliparea
|
||||
if (scrollbar0.IsVisible())
|
||||
cliparea.right -= scrollbar0.GetOuterRect().GetWidth();
|
||||
if (scrollbar1.IsVisible())
|
||||
cliparea.bottom -= scrollbar1.GetOuterRect().GetHeight();
|
||||
|
||||
CGUIObjectEventBroadcaster::RecurseVisibleObject(this, &IGUIObject::DrawInArea, canvas, cliparea);
|
||||
m_Drawing = false;
|
||||
}
|
||||
|
||||
void CScrollPanel::Setup()
|
||||
{
|
||||
IGUIScrollBar& scrollbar0 = GetScrollBar(0);
|
||||
IGUIScrollBar& scrollbar1 = GetScrollBar(1);
|
||||
|
||||
m_CachedActualSize = m_CachedLayoutActualSize;
|
||||
|
||||
if (HasVerticalScrollBar() && m_CachedLayoutActualSize.GetHeight() < m_MinHeight)
|
||||
m_CachedActualSize.bottom = m_CachedLayoutActualSize.top + m_MinHeight;
|
||||
|
||||
if (HasHorizontalScrollBar() && m_CachedLayoutActualSize.GetWidth() < m_MinWidth)
|
||||
m_CachedActualSize.right = m_CachedLayoutActualSize.left + m_MinWidth;
|
||||
|
||||
for (IGUIObject* child : m_Children)
|
||||
child->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateCachedSize);
|
||||
|
||||
float vscroll = scrollbar0.GetPos();
|
||||
float hscroll = scrollbar1.GetPos();
|
||||
float maxVRange = 0;
|
||||
float maxHRange = 0;
|
||||
|
||||
for (IGUIObject* child : m_Children)
|
||||
{
|
||||
if (child->IsHiddenOrGhost())
|
||||
continue;
|
||||
CRect childSize = child->GetComputedSize();
|
||||
maxVRange = std::max(maxVRange, childSize.bottom);
|
||||
maxHRange = std::max(maxHRange, childSize.right);
|
||||
}
|
||||
|
||||
maxVRange -= m_CachedLayoutActualSize.top;
|
||||
maxHRange -= m_CachedLayoutActualSize.left;
|
||||
|
||||
scrollbar0.SetScrollRange(HasVerticalScrollBar() ? maxVRange : m_CachedLayoutActualSize.GetHeight());
|
||||
scrollbar0.SetScrollSpace(m_CachedLayoutActualSize.GetHeight());
|
||||
scrollbar0.SetX(m_CachedLayoutActualSize.right);
|
||||
scrollbar0.SetY(m_CachedLayoutActualSize.top);
|
||||
scrollbar0.SetZ(GetBufferedZ());
|
||||
scrollbar0.SetLength(m_CachedLayoutActualSize.GetHeight());
|
||||
|
||||
scrollbar1.SetScrollRange(HasHorizontalScrollBar() ? maxHRange : m_CachedLayoutActualSize.GetWidth());
|
||||
scrollbar1.SetScrollSpace(m_CachedLayoutActualSize.GetWidth());
|
||||
scrollbar1.SetX(m_CachedLayoutActualSize.left);
|
||||
scrollbar1.SetY(m_CachedLayoutActualSize.bottom);
|
||||
scrollbar1.SetZ(GetBufferedZ());
|
||||
scrollbar1.SetLength(m_CachedLayoutActualSize.GetWidth());
|
||||
|
||||
if (HasVerticalScrollBar() && HasHorizontalScrollBar() && scrollbar0.IsVisible())
|
||||
{
|
||||
scrollbar1.SetLength(m_CachedLayoutActualSize.GetWidth() - scrollbar0.GetOuterRect().GetWidth());
|
||||
scrollbar1.SetScrollSpace(m_CachedLayoutActualSize.GetWidth() + scrollbar0.GetOuterRect().GetWidth());
|
||||
}
|
||||
|
||||
if (HasHorizontalScrollBar() && HasVerticalScrollBar() && scrollbar1.IsVisible())
|
||||
{
|
||||
scrollbar0.SetLength(m_CachedLayoutActualSize.GetHeight() - scrollbar1.GetOuterRect().GetHeight());
|
||||
scrollbar0.SetScrollSpace(m_CachedLayoutActualSize.GetHeight() - scrollbar1.GetOuterRect().GetHeight());
|
||||
}
|
||||
|
||||
if (HasVerticalScrollBar() && maxVRange < vscroll)
|
||||
{
|
||||
vscroll = maxVRange;
|
||||
scrollbar0.SetPos(vscroll);
|
||||
}
|
||||
|
||||
if (HasHorizontalScrollBar() && maxHRange < hscroll)
|
||||
{
|
||||
hscroll = maxHRange;
|
||||
scrollbar1.SetPos(hscroll);
|
||||
}
|
||||
|
||||
UpdateScrollPosition(vscroll, hscroll);
|
||||
}
|
||||
|
||||
void CScrollPanel::UpdateScrollPosition(float scroll, float hscroll)
|
||||
{
|
||||
IGUIScrollBar& scrollbar0 = GetScrollBar(0);
|
||||
IGUIScrollBar& scrollbar1 = GetScrollBar(1);
|
||||
|
||||
m_CachedActualSize = m_CachedLayoutActualSize;
|
||||
|
||||
if (HasVerticalScrollBar() && m_CachedLayoutActualSize.GetHeight() < m_MinHeight)
|
||||
m_CachedActualSize.bottom = m_CachedLayoutActualSize.top + m_MinHeight;
|
||||
|
||||
if (HasHorizontalScrollBar() && m_CachedLayoutActualSize.GetWidth() < m_MinWidth)
|
||||
m_CachedActualSize.right = m_CachedLayoutActualSize.left + m_MinWidth;
|
||||
|
||||
m_CachedActualSize.top -= scroll;
|
||||
m_CachedActualSize.bottom -= scroll;
|
||||
|
||||
m_CachedActualSize.left -= hscroll;
|
||||
m_CachedActualSize.right -= hscroll;
|
||||
|
||||
// upddate scroll bars size base on m_Width
|
||||
if (scrollbar0.IsVisible())
|
||||
m_CachedActualSize.right -= scrollbar0.GetOuterRect().GetWidth();
|
||||
if (scrollbar1.IsVisible())
|
||||
m_CachedActualSize.bottom -= scrollbar1.GetOuterRect().GetHeight();
|
||||
|
||||
for (IGUIObject* child : m_Children)
|
||||
child->RecurseObject(&IGUIObject::IsHiddenOrGhost, &IGUIObject::UpdateCachedSize);
|
||||
}
|
||||
|
||||
void CScrollPanel::ResetScrollPosition(EScrollOrientation orientation)
|
||||
{
|
||||
IGUIScrollBar& scrollbar0 = GetScrollBar(0);
|
||||
IGUIScrollBar& scrollbar1 = GetScrollBar(1);
|
||||
|
||||
if (orientation == EScrollOrientation::BOTH || orientation == EScrollOrientation::VERTICAL)
|
||||
scrollbar0.SetPos(0);
|
||||
|
||||
if (orientation == EScrollOrientation::BOTH || orientation == EScrollOrientation::HORIZONTAL)
|
||||
scrollbar1.SetPos(0);
|
||||
}
|
||||
62
source/gui/ObjectTypes/CScrollPanel.h
Normal file
62
source/gui/ObjectTypes/CScrollPanel.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/* Copyright (C) 20244 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_CSCROLLPANEL
|
||||
#define INCLUDED_CSCROLLPANEL
|
||||
|
||||
#include "gui/ObjectBases/IGUIPanel.h"
|
||||
#include "gui/ObjectBases/IGUIScrollBarOwner.h"
|
||||
#include "gui/SettingTypes/EScrollOrientation.h"
|
||||
#include "ps/CStr.h"
|
||||
|
||||
class CScrollPanel : public IGUIPanel, public IGUIScrollBarOwner
|
||||
{
|
||||
GUI_OBJECT(CScrollPanel)
|
||||
mutable std::vector<IGUIObject*> m_ModifiedChildren; // To store the modified vector
|
||||
public:
|
||||
CScrollPanel(CGUI& pGUI);
|
||||
virtual ~CScrollPanel();
|
||||
|
||||
virtual void UpdateCachedSize();
|
||||
virtual void ResetStates();
|
||||
|
||||
void Setup();
|
||||
|
||||
void ResetScrollPosition(EScrollOrientation orientation = EScrollOrientation::BOTH);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @see IGUIObject#HandleMessage()
|
||||
*/
|
||||
virtual void HandleMessage(SGUIMessage& Message);
|
||||
|
||||
void UpdateScrollPosition(float vscroll, float hscroll);
|
||||
|
||||
bool HasHorizontalScrollBar() const { return *m_Orientation == EScrollOrientation::HORIZONTAL || *m_Orientation == EScrollOrientation::BOTH; };
|
||||
bool HasVerticalScrollBar() const { return *m_Orientation == EScrollOrientation::VERTICAL || *m_Orientation == EScrollOrientation::BOTH; };
|
||||
|
||||
virtual void Draw(CCanvas2D& canvas);
|
||||
|
||||
virtual void CreateJSObject();
|
||||
|
||||
CGUISimpleSetting<EScrollOrientation> m_Orientation;
|
||||
CGUISimpleSetting<CStr> m_ScrollBarStyle;
|
||||
CGUISimpleSetting<int> m_MinWidth;
|
||||
CGUISimpleSetting<int> m_MinHeight;
|
||||
};
|
||||
|
||||
#endif // INCLUDED_CSCROLLPANEL
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2022 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -78,6 +78,7 @@ void CSlider::HandleMessage(SGUIMessage& Message)
|
|||
{
|
||||
if (m_Pressed)
|
||||
break;
|
||||
Message.Skip(false);
|
||||
IncrementallyChangeValue(-0.01f);
|
||||
break;
|
||||
}
|
||||
|
|
@ -85,6 +86,7 @@ void CSlider::HandleMessage(SGUIMessage& Message)
|
|||
{
|
||||
if (m_Pressed)
|
||||
break;
|
||||
Message.Skip(false);
|
||||
IncrementallyChangeValue(0.01f);
|
||||
break;
|
||||
}
|
||||
|
|
@ -109,8 +111,8 @@ void CSlider::Draw(CCanvas2D& canvas)
|
|||
CRect sliderLine(m_CachedActualSize);
|
||||
sliderLine.left += m_ButtonSide / 2.0f;
|
||||
sliderLine.right -= m_ButtonSide / 2.0f;
|
||||
m_pGUI.DrawSprite(IsEnabled() ? m_SpriteBar : m_SpriteBarDisabled, canvas, sliderLine);
|
||||
m_pGUI.DrawSprite(IsEnabled() ? m_Sprite : m_SpriteDisabled, canvas, GetButtonRect());
|
||||
m_pGUI.DrawSprite(IsEnabled() ? m_SpriteBar : m_SpriteBarDisabled, canvas, sliderLine, m_VisibleArea);
|
||||
m_pGUI.DrawSprite(IsEnabled() ? m_Sprite : m_SpriteDisabled, canvas, GetButtonRect(), m_VisibleArea);
|
||||
}
|
||||
|
||||
void CSlider::UpdateValue()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -130,7 +130,8 @@ const CStrW& CText::GetTooltipText() const
|
|||
void CText::HandleMessage(SGUIMessage& Message)
|
||||
{
|
||||
IGUIObject::HandleMessage(Message);
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
if (m_ScrollBar)
|
||||
IGUIScrollBarOwner::HandleMessage(Message);
|
||||
//IGUITextOwner::HandleMessage(Message); <== placed it after the switch instead!
|
||||
|
||||
switch (Message.type)
|
||||
|
|
@ -148,24 +149,6 @@ void CText::HandleMessage(SGUIMessage& Message)
|
|||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
case GUIM_LOAD:
|
||||
{
|
||||
GetScrollBar(0).SetX(m_CachedActualSize.right);
|
||||
|
|
@ -185,18 +168,16 @@ void CText::HandleMessage(SGUIMessage& Message)
|
|||
|
||||
void CText::Draw(CCanvas2D& canvas)
|
||||
{
|
||||
m_pGUI.DrawSprite(m_Sprite, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(m_Sprite, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
|
||||
float scroll = 0.f;
|
||||
if (m_ScrollBar)
|
||||
scroll = GetScrollBar(0).GetPos();
|
||||
|
||||
// Clipping area (we'll have to subtract the scrollbar)
|
||||
CRect cliparea;
|
||||
CRect cliparea = m_VisibleArea ? m_VisibleArea : m_CachedActualSize;
|
||||
if (m_Clip)
|
||||
{
|
||||
cliparea = m_CachedActualSize;
|
||||
|
||||
if (m_ScrollBar)
|
||||
{
|
||||
// subtract scrollbar from cliparea
|
||||
|
|
@ -222,5 +203,5 @@ void CText::Draw(CCanvas2D& canvas)
|
|||
IGUIScrollBarOwner::Draw(canvas);
|
||||
|
||||
// Draw the overlays last
|
||||
m_pGUI.DrawSprite(m_SpriteOverlay, canvas, m_CachedActualSize);
|
||||
m_pGUI.DrawSprite(m_SpriteOverlay, canvas, m_CachedActualSize, m_VisibleArea);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2020 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -35,13 +35,15 @@ enum EGUIMessageType
|
|||
GUIM_MOUSE_DOWN_LEFT,
|
||||
GUIM_MOUSE_DOWN_RIGHT,
|
||||
GUIM_MOUSE_DBLCLICK_LEFT,
|
||||
GUIM_MOUSE_DBLCLICK_LEFT_ITEM, // Triggered when doubleclicking on a list item
|
||||
GUIM_MOUSE_DBLCLICK_LEFT_ITEM, // Triggered when doubleclicking on a list item.
|
||||
GUIM_MOUSE_DBLCLICK_RIGHT,
|
||||
GUIM_MOUSE_RELEASE_LEFT,
|
||||
GUIM_MOUSE_RELEASE_RIGHT,
|
||||
GUIM_MOUSE_WHEEL_UP,
|
||||
GUIM_MOUSE_WHEEL_DOWN,
|
||||
GUIM_SETTINGS_UPDATED, // SGUIMessage.m_Value = name of setting
|
||||
GUIM_MOUSE_WHEEL_LEFT,
|
||||
GUIM_MOUSE_WHEEL_RIGHT,
|
||||
GUIM_SETTINGS_UPDATED, // SGUIMessage.m_Value = name of setting.
|
||||
GUIM_PRESSED,
|
||||
GUIM_KEYDOWN,
|
||||
GUIM_RELEASED,
|
||||
|
|
@ -55,8 +57,10 @@ enum EGUIMessageType
|
|||
GUIM_DOUBLE_PRESSED_MOUSE_RIGHT,
|
||||
GUIM_PRESSED_MOUSE_RELEASE,
|
||||
GUIM_PRESSED_MOUSE_RELEASE_RIGHT,
|
||||
GUIM_TAB, // Used by CInput
|
||||
GUIM_TEXTEDIT
|
||||
GUIM_TAB, // Used by CInput.
|
||||
GUIM_TEXTEDIT,
|
||||
GUIM_CHILD_RESIZED, // SGUIMessage.m_Value = name of the object that changed size, used for inform to parent.
|
||||
GUIM_CHILD_TOGGLE_VISIBILITY, // SGUIMessage.m_Value = name of the object that changed visibility used for inform to parent.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
#include "precompiled.h"
|
||||
|
||||
#include "gui/ObjectBases/IGUIObject.h"
|
||||
#include "gui/SettingTypes/EScrollOrientation.h"
|
||||
#include "gui/SettingTypes/CGUIColor.h"
|
||||
#include "gui/SettingTypes/CGUIList.h"
|
||||
#include "gui/SettingTypes/CGUISeries.h"
|
||||
|
|
@ -310,6 +311,49 @@ template<> bool Script::FromJSVal<EAlign>(const ScriptRequest& rq, JS::HandleVal
|
|||
return true;
|
||||
}
|
||||
|
||||
template<> void Script::ToJSVal<EScrollOrientation>(const ScriptRequest& rq, JS::MutableHandleValue ret, const EScrollOrientation& val)
|
||||
{
|
||||
std::string word;
|
||||
switch (val)
|
||||
{
|
||||
case EScrollOrientation::HORIZONTAL:
|
||||
word = "horizontal";
|
||||
break;
|
||||
case EScrollOrientation::VERTICAL:
|
||||
word = "vertical";
|
||||
break;
|
||||
case EScrollOrientation::BOTH:
|
||||
word = "both";
|
||||
break;
|
||||
default:
|
||||
word = "error";
|
||||
ScriptException::Raise(rq, "Invalid scroll orientation (should be 'vertical', 'horizontal' or 'both')");
|
||||
break;
|
||||
}
|
||||
ToJSVal(rq, ret, word);
|
||||
}
|
||||
|
||||
template <> bool Script::FromJSVal<EScrollOrientation>(const ScriptRequest& rq, JS::HandleValue v, EScrollOrientation& out)
|
||||
{
|
||||
std::string word;
|
||||
FromJSVal(rq, v, word);
|
||||
|
||||
if (word == "horizontal")
|
||||
out = EScrollOrientation::HORIZONTAL;
|
||||
else if (word == "vertical")
|
||||
out = EScrollOrientation::VERTICAL;
|
||||
else if (word == "both")
|
||||
out = EScrollOrientation::BOTH;
|
||||
else
|
||||
{
|
||||
out = EScrollOrientation::VERTICAL;
|
||||
LOGERROR("Invalid scroll orientation (should be 'vertical', 'horizontal' or 'both')");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<> void Script::ToJSVal<CGUISpriteInstance>(const ScriptRequest& rq, JS::MutableHandleValue ret, const CGUISpriteInstance& val)
|
||||
{
|
||||
ToJSVal(rq, ret, val.GetName());
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -23,6 +23,7 @@
|
|||
#include "gui/ObjectTypes/CButton.h"
|
||||
#include "gui/ObjectTypes/CList.h"
|
||||
#include "gui/ObjectTypes/CMiniMap.h"
|
||||
#include "gui/ObjectTypes/CScrollPanel.h"
|
||||
#include "gui/ObjectTypes/CText.h"
|
||||
|
||||
// Called for every specialization - adds the common interface.
|
||||
|
|
@ -66,3 +67,10 @@ template<> void JSI_GUIProxy<CMiniMap>::CreateFunctions(const ScriptRequest& rq,
|
|||
CreateFunction<&CMiniMap::Flare>(rq, cache, "flare");
|
||||
}
|
||||
DECLARE_GUIPROXY(CMiniMap);
|
||||
|
||||
// CScrollPanel
|
||||
template<> void JSI_GUIProxy<CScrollPanel>::CreateFunctions(const ScriptRequest& rq, GUIProxyProps* cache)
|
||||
{
|
||||
CreateFunction<&CScrollPanel::ResetScrollPosition>(rq, cache, "resetScrollPosition");
|
||||
}
|
||||
DECLARE_GUIPROXY(CScrollPanel);
|
||||
|
|
|
|||
28
source/gui/SettingTypes/EScrollOrientation.h
Normal file
28
source/gui/SettingTypes/EScrollOrientation.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 0 A.D. is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_ESCROLLORIENTATION
|
||||
#define INCLUDED_ESCROLLORIENTATION
|
||||
|
||||
enum class EScrollOrientation
|
||||
{
|
||||
HORIZONTAL,
|
||||
VERTICAL,
|
||||
BOTH
|
||||
};
|
||||
|
||||
#endif // INCLUDED_ESCROLLORIENTATION
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -219,3 +219,16 @@ CRect CRect::Scale(float x, float y) const
|
|||
{
|
||||
return CRect(left * x, top * y, right * x, bottom * y);
|
||||
}
|
||||
|
||||
bool CRect::IntersectWith(const CRect& a) const
|
||||
{
|
||||
return left < a.right && right > a.left && top < a.bottom && bottom > a.top;
|
||||
}
|
||||
|
||||
CRect CRect::Intersection(const CRect& a) const
|
||||
{
|
||||
if (!IntersectWith(a))
|
||||
return CRect();
|
||||
|
||||
return CRect(std::max(left, a.left), std::max(top, a.top), std::min(right, a.right), std::min(bottom, a.bottom));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2021 Wildfire Games.
|
||||
/* Copyright (C) 2024 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -58,6 +58,8 @@ public:
|
|||
void operator-=(const CVector2D& a);
|
||||
void operator-=(const CSize2D& a);
|
||||
|
||||
operator bool() const { return right - left > 0 && bottom - top > 0; }
|
||||
|
||||
/**
|
||||
* @return Width of Rectangle
|
||||
*/
|
||||
|
|
@ -107,6 +109,10 @@ public:
|
|||
|
||||
CRect Scale(float x, float y) const;
|
||||
|
||||
bool IntersectWith(const CRect& a) const;
|
||||
|
||||
CRect Intersection(const CRect& a) const;
|
||||
|
||||
/**
|
||||
* Returning CVector2D representing each corner.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue