eepp: Added UIStackLayout. Minor fixes.

This commit is contained in:
Martín Lucas Golini
2023-05-26 01:14:49 -03:00
parent af284a4c1b
commit 947648944f
15 changed files with 381 additions and 40 deletions

View File

@@ -5,9 +5,8 @@
#include <cstdlib>
#include <cstring>
#include <eepp/config.hpp>
#include <map>
#include <string>
#include <unordered_map>
namespace EE {
@@ -23,10 +22,9 @@ class EE_API AllocatedPointer {
bool mTrack;
};
typedef std::map<void*, AllocatedPointer> AllocatedPointerMap;
typedef std::unordered_map<void*, AllocatedPointer> AllocatedPointerMap;
typedef AllocatedPointerMap::iterator AllocatedPointerMapIt;
#if defined( __GNUC__ ) && __GNUC__ >= 12
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuse-after-free"
@@ -163,7 +161,6 @@ class EE_API MemoryManager {
#endif
} // namespace EE
#endif

View File

@@ -4,6 +4,7 @@
#include <cstdlib>
#include <eepp/core.hpp>
#include <eepp/system/time.hpp>
#include <map>
using namespace EE::System;
namespace EE { namespace Scene {

View File

@@ -4,6 +4,7 @@
#include <eepp/system/iostream.hpp>
#include <eepp/system/mutex.hpp>
#include <eepp/system/scopedbuffer.hpp>
#include <map>
namespace EE { namespace System {

View File

@@ -36,6 +36,7 @@
#include <eepp/ui/uispinbox.hpp>
#include <eepp/ui/uisplitter.hpp>
#include <eepp/ui/uisprite.hpp>
#include <eepp/ui/uistacklayout.hpp>
#include <eepp/ui/uistyle.hpp>
#include <eepp/ui/uitab.hpp>
#include <eepp/ui/uitableview.hpp>

View File

@@ -100,6 +100,7 @@ enum UINodeType {
UI_TYPE_TABLECELL,
UI_TYPE_LISTVIEW,
UI_TYPE_CONSOLE,
UI_TYPE_STACK_LAYOUT,
UI_TYPE_MODULES = 10000,
UI_TYPE_TERMINAL = 10001,
UI_TYPE_USER = 100000

View File

@@ -7,10 +7,6 @@ namespace EE { namespace UI {
class EE_API UILayout : public UIWidget {
public:
static UILayout* New();
UILayout();
virtual Uint32 getType() const;
virtual bool isType( const Uint32& type ) const;
@@ -23,10 +19,12 @@ class EE_API UILayout : public UIWidget {
void setGravityOwner( bool gravityOwner );
bool isPacking() const { return mPacking; }
protected:
friend class UISceneNode;
UILayout( const std::string& tag );
explicit UILayout( const std::string& tag );
virtual void onSizeChange();
@@ -48,6 +46,8 @@ class EE_API UILayout : public UIWidget {
bool mDirtyLayout{ false };
bool mPacking{ false };
bool mGravityOwner{ false };
Sizef getSizeFromLayoutPolicy();
};
}} // namespace EE::UI

View File

@@ -15,10 +15,6 @@ class EE_API UILinearLayout : public UILayout {
static UILinearLayout* NewHorizontal();
UILinearLayout();
UILinearLayout( const std::string& tag, const UIOrientation& orientation );
virtual Uint32 getType() const;
virtual bool isType( const Uint32& type ) const;
@@ -27,8 +23,6 @@ class EE_API UILinearLayout : public UILayout {
UILinearLayout* setOrientation( const UIOrientation& getOrientation );
UILinearLayout* add( UIWidget* widget );
virtual bool applyProperty( const StyleSheetProperty& attribute );
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
@@ -38,11 +32,13 @@ class EE_API UILinearLayout : public UILayout {
void updateLayout();
bool isPacking() const;
protected:
UIOrientation mOrientation;
UILinearLayout();
UILinearLayout( const std::string& tag, const UIOrientation& orientation );
virtual Uint32 onMessage( const NodeMessage* Msg );
void packVertical();

View File

@@ -0,0 +1,40 @@
#ifndef EE_UI_UISTACKLAYOUT_HPP
#define EE_UI_UISTACKLAYOUT_HPP
#include <eepp/ui/uilayout.hpp>
namespace EE { namespace UI {
class EE_API UIStackLayout : public UILayout {
public:
static UIStackLayout* New();
static UIStackLayout* NewWithTag( const std::string& tag = "stacklayout" );
virtual Uint32 getType() const;
virtual bool isType( const Uint32& type ) const;
virtual bool applyProperty( const StyleSheetProperty& attribute );
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
const Uint32& propertyIndex = 0 ) const;
virtual std::vector<PropertyId> getPropertiesImplemented() const;
void updateLayout();
protected:
UIStackLayout();
virtual Uint32 onMessage( const NodeMessage* Msg );
explicit UIStackLayout( const std::string& tag );
void applySizePolicyOnChilds();
};
}} // namespace EE::UI
#endif // EE_UI_UISTACKLAYOUT_HPP

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 10.0.0, 2023-04-18T20:30:28. -->
<!-- Written by QtCreator 10.0.1, 2023-05-25T23:52:25. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@@ -110,7 +110,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{388e5431-b31b-42b3-b9ad-9002d279d75d}</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">10</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">19</value>
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">15</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">../../make/linux</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
@@ -187,7 +187,7 @@
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
<value type="QString" key="ProjectExplorer.ProcessStep.Arguments">gmake</value>
<value type="QString" key="ProjectExplorer.ProcessStep.Arguments">--with-debug-symbols gmake</value>
<value type="QString" key="ProjectExplorer.ProcessStep.Command">premake4</value>
<value type="QString" key="ProjectExplorer.ProcessStep.WorkingDirectory">%{buildDir}../../../</value>
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.ProcessStep</value>

View File

@@ -461,6 +461,7 @@
../../include/eepp/window/window.hpp
../../Makefile
../../Makefile.base
../../include/eepp/ui/uistacklayout.hpp
../../premake4.lua
../../premake5.lua
../../src/eepp/audio/alcheck.cpp
@@ -913,6 +914,7 @@
../../src/eepp/ui/uispinbox.cpp
../../src/eepp/ui/uisplitter.cpp
../../src/eepp/ui/uisprite.cpp
../../src/eepp/ui/uistacklayout.cpp
../../src/eepp/ui/uistackwidget.cpp
../../src/eepp/ui/uistate.cpp
../../src/eepp/ui/uistyle.cpp

View File

@@ -15,6 +15,9 @@ UIIconTheme::~UIIconTheme() {
UIIconTheme::UIIconTheme( const std::string& name ) : mName( name ) {}
UIIconTheme* UIIconTheme::add( UIIcon* icon ) {
auto iconExists = mIcons.find( icon->getName() );
if ( iconExists != mIcons.end() )
eeDelete( iconExists->second );
mIcons[icon->getName()] = icon;
return this;
}

View File

@@ -3,15 +3,6 @@
namespace EE { namespace UI {
UILayout* UILayout::New() {
return eeNew( UILayout, () );
}
UILayout::UILayout() : UIWidget( "layout" ) {
mNodeFlags |= NODE_FLAG_LAYOUT;
unsetFlags( UI_TAB_FOCUSABLE );
}
UILayout::UILayout( const std::string& tag ) : UIWidget( tag ) {
mNodeFlags |= NODE_FLAG_LAYOUT;
unsetFlags( UI_TAB_FOCUSABLE );
@@ -77,6 +68,39 @@ void UILayout::setLayoutDirty() {
}
}
Sizef UILayout::getSizeFromLayoutPolicy() {
Sizef size( getPixelsSize() );
if ( getLayoutWidthPolicy() == SizePolicy::MatchParent ) {
Float w =
getParent()->getPixelsSize().getWidth() - mLayoutMarginPx.Left - mLayoutMarginPx.Right;
if ( getParent()->isType( UI_TYPE_LAYOUT ) ) {
UILayout* pLay = static_cast<UILayout*>( getParent() );
w = w - pLay->getPixelsPadding().Left - pLay->getPixelsPadding().Right;
}
if ( (int)w != (int)getPixelsSize().getWidth() )
size.setWidth( w );
}
if ( getLayoutHeightPolicy() == SizePolicy::MatchParent ) {
Float h =
getParent()->getPixelsSize().getHeight() - mLayoutMarginPx.Top - mLayoutMarginPx.Bottom;
if ( getParent()->isType( UI_TYPE_LAYOUT ) ) {
UILayout* pLay = static_cast<UILayout*>( getParent() );
h = h - pLay->getPixelsPadding().Top - pLay->getPixelsPadding().Bottom;
}
if ( (int)h != (int)getPixelsSize().getHeight() ) {
size.setHeight( h );
}
}
return size;
}
bool UILayout::isGravityOwner() const {
return mGravityOwner;
}

View File

@@ -50,11 +50,6 @@ UILinearLayout* UILinearLayout::setOrientation( const UIOrientation& orientation
return this;
}
UILinearLayout* UILinearLayout::add( UIWidget* widget ) {
widget->setParent( this );
return this;
}
void UILinearLayout::updateLayout() {
if ( mOrientation == UIOrientation::Vertical )
packVertical();
@@ -63,10 +58,6 @@ void UILinearLayout::updateLayout() {
mDirtyLayout = false;
}
bool UILinearLayout::isPacking() const {
return mPacking;
}
void UILinearLayout::applyWidthPolicyOnChilds() {
Node* child = mChild;

View File

@@ -0,0 +1,283 @@
#include <eepp/ui/uistacklayout.hpp>
namespace EE { namespace UI {
UIStackLayout* UIStackLayout::NewWithTag( const std::string& tag ) {
return eeNew( UIStackLayout, ( tag ) );
}
UIStackLayout* UIStackLayout::New() {
return eeNew( UIStackLayout, () );
}
UIStackLayout::UIStackLayout() : UILayout( "stacklayout" ) {
mFlags |= UI_OWNS_CHILDS_POSITION;
setClipType( ClipType::ContentBox );
}
UIStackLayout::UIStackLayout( const std::string& tag ) : UILayout( tag ) {
mFlags |= UI_OWNS_CHILDS_POSITION;
setClipType( ClipType::ContentBox );
}
Uint32 UIStackLayout::getType() const {
return UI_TYPE_STACK_LAYOUT;
}
bool UIStackLayout::isType( const Uint32& type ) const {
return UIStackLayout::getType() == type ? true : UILayout::isType( type );
}
void UIStackLayout::applySizePolicyOnChilds() {
Node* child = mChild;
while ( NULL != child ) {
if ( child->isWidget() && child->isVisible() ) {
UIWidget* widget = static_cast<UIWidget*>( child );
switch ( widget->getLayoutWidthPolicy() ) {
case SizePolicy::WrapContent: {
widget->setFlags( UI_AUTO_SIZE );
break;
}
case SizePolicy::MatchParent: {
int w = getPixelsSize().getWidth() - widget->getLayoutPixelsMargin().Left -
widget->getLayoutPixelsMargin().Right - mPaddingPx.Left -
mPaddingPx.Right;
if ( (int)widget->getPixelsSize().getWidth() != w && w > 0 )
widget->setPixelsSize( w, widget->getPixelsSize().getHeight() );
break;
}
case SizePolicy::Fixed:
default: {
}
}
switch ( widget->getLayoutHeightPolicy() ) {
case SizePolicy::WrapContent: {
widget->setFlags( UI_AUTO_SIZE );
break;
}
case SizePolicy::MatchParent: {
int h = getPixelsSize().getHeight() - widget->getLayoutPixelsMargin().Top -
widget->getLayoutPixelsMargin().Bottom - mPaddingPx.Top -
mPaddingPx.Bottom;
if ( h != (int)widget->getPixelsSize().getHeight() && h > 0 )
widget->setPixelsSize( widget->getPixelsSize().getWidth(), h );
break;
}
case SizePolicy::Fixed:
default: {
}
}
}
child = child->getNextNode();
}
}
std::string UIStackLayout::getPropertyString( const PropertyDefinition* propertyDef,
const Uint32& propertyIndex ) const {
if ( NULL == propertyDef )
return "";
switch ( propertyDef->getPropertyId() ) {
case PropertyId::GravityOwner:
return isGravityOwner() ? "true" : "false";
default:
return UILayout::getPropertyString( propertyDef, propertyIndex );
}
}
std::vector<PropertyId> UIStackLayout::getPropertiesImplemented() const {
auto props = UILayout::getPropertiesImplemented();
auto local = { PropertyId::GravityOwner };
props.insert( props.end(), local.begin(), local.end() );
return props;
}
bool UIStackLayout::applyProperty( const StyleSheetProperty& attribute ) {
if ( !checkPropertyDefinition( attribute ) )
return false;
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
case PropertyId::GravityOwner: {
setGravityOwner( attribute.asBool() );
break;
}
default:
return UILayout::applyProperty( attribute );
}
return true;
}
Uint32 UIStackLayout::onMessage( const NodeMessage* Msg ) {
switch ( Msg->getMsg() ) {
case NodeMessage::LayoutAttributeChange: {
tryUpdateLayout();
return 1;
}
}
return 0;
}
struct NodeLine {
std::vector<UIWidget*> nodes;
Float maxY{ 0 };
Float width{ 0 };
};
void UIStackLayout::updateLayout() {
if ( mPacking )
return;
mPacking = true;
Sizef size( getPixelsSize() );
Sizef nsize( getSizeFromLayoutPolicy() );
if ( size != nsize )
setInternalPixelsSize( nsize );
applySizePolicyOnChilds();
Float curX = mPaddingPx.Left;
Node* child = mChild;
std::vector<NodeLine> lines = { {} };
Uint32 curLine = 0;
bool addedLine = false;
auto addLine = [&]() {
curX = mPaddingPx.Left;
++curLine;
lines.push_back( { {} } );
addedLine = true;
};
while ( NULL != child ) {
if ( child->isWidget() && child->isVisible() ) {
UIWidget* widget = static_cast<UIWidget*>( child );
const Rectf& margin = widget->getLayoutPixelsMargin();
if ( curX + margin.Left + widget->getPixelsSize().getWidth() >= mSize.getWidth() &&
!addedLine && !lines[curLine].nodes.empty() )
addLine();
addedLine = false;
curX += eeceil( margin.Left );
Vector2f pos( curX, mPaddingPx.Top );
widget->setPixelsPosition( pos );
curX += eeceil( widget->getPixelsSize().getWidth() + margin.Right );
lines[curLine].nodes.push_back( widget );
lines[curLine].width = curX;
lines[curLine].maxY =
eeceil( eemax( lines[curLine].maxY, ( widget->getPixelsSize().getHeight() +
widget->getLayoutPixelsMargin().Top +
widget->getLayoutPixelsMargin().Bottom ) ) );
if ( curX > mSize.getWidth() )
addLine();
}
child = child->getNextNode();
}
Float maxY = mPaddingPx.Top;
Float height = 0.f;
Float totHeight = maxY;
for ( const auto& line : lines ) {
height += line.maxY;
totHeight += line.maxY;
}
totHeight += mPaddingPx.Bottom;
if ( getLayoutHeightPolicy() == SizePolicy::WrapContent ) {
if ( totHeight != (int)getPixelsSize().getHeight() ) {
setInternalPixelsHeight( totHeight );
notifyLayoutAttrChangeParent();
}
}
for ( const auto& line : lines ) {
Float xDisplacement = 0.f;
Float yDisplacement = 0.f;
switch ( Font::getHorizontalAlign( getHorizontalAlign() ) ) {
case UI_HALIGN_CENTER:
xDisplacement = eeceil( ( getPixelsSize().getWidth() - line.width ) * 0.5f );
break;
case UI_HALIGN_RIGHT:
xDisplacement = getPixelsSize().getWidth() - line.width;
break;
case UI_HALIGN_LEFT:
default:
break;
}
Float innerHeight = getPixelsSize().getHeight() - mPaddingPx.Top - mPaddingPx.Bottom;
if ( height < innerHeight ) {
switch ( Font::getVerticalAlign( getVerticalAlign() ) ) {
case UI_VALIGN_CENTER:
yDisplacement = eeceil( ( innerHeight - height ) * 0.5f );
break;
case UI_VALIGN_BOTTOM:
yDisplacement = ( innerHeight - height );
break;
case UI_VALIGN_TOP:
default:
break;
}
}
for ( const auto& widget : line.nodes ) {
Vector2f pos( widget->getPixelsPosition() );
switch ( Font::getHorizontalAlign( getHorizontalAlign() ) ) {
case UI_HALIGN_CENTER:
case UI_HALIGN_RIGHT:
pos.x = xDisplacement + widget->getPixelsPosition().x;
break;
case UI_HALIGN_LEFT:
default:
break;
}
switch ( Font::getVerticalAlign( widget->getLayoutGravity() ) ) {
case UI_VALIGN_CENTER:
pos.y = yDisplacement + maxY +
eeceil( ( line.maxY - widget->getPixelsSize().getHeight() ) * 0.5f );
break;
case UI_VALIGN_BOTTOM:
pos.y = yDisplacement + maxY + line.maxY - widget->getPixelsSize().getHeight();
break;
case UI_VALIGN_TOP:
default:
pos.y = yDisplacement + maxY + widget->getLayoutPixelsMargin().Top;
break;
}
widget->setPixelsPosition( pos );
}
maxY += line.maxY;
}
if ( getParent()->isUINode() &&
( !getParent()->asType<UINode>()->ownsChildPosition() || isGravityOwner() ) ) {
alignAgainstLayout();
}
mPacking = false;
mDirtyLayout = false;
}
}} // namespace EE::UI

View File

@@ -21,6 +21,7 @@
#include <eepp/ui/uispinbox.hpp>
#include <eepp/ui/uisplitter.hpp>
#include <eepp/ui/uisprite.hpp>
#include <eepp/ui/uistacklayout.hpp>
#include <eepp/ui/uistackwidget.hpp>
#include <eepp/ui/uitab.hpp>
#include <eepp/ui/uitableview.hpp>
@@ -82,7 +83,7 @@ void UIWidgetCreator::createBaseWidgetList() {
registeredWidget["textureregion"] = UITextureRegion::New;
registeredWidget["touchdraggable"] = UITouchDraggableWidget::New;
registeredWidget["gridlayout"] = UIGridLayout::New;
registeredWidget["layout"] = UILayout::New;
registeredWidget["stacklayout"] = UIStackLayout::New;
registeredWidget["viewpager"] = UIViewPager::New;
registeredWidget["codeeditor"] = UICodeEditor::New;
registeredWidget["splitter"] = UISplitter::New;