mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-11 17:17:42 +03:00
Added UIHTMLListItem to handle list items properly.
This commit is contained in:
@@ -148,52 +148,12 @@ ol > li {
|
||||
padding-left: 2em;
|
||||
}
|
||||
|
||||
ol > li {
|
||||
background-tint: var(--font);
|
||||
background-position: 0.6em 0.3em;
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
ol > li:nth-child(1) {
|
||||
background-image: glyph("monospace", 1em, "1");
|
||||
}
|
||||
|
||||
ol > li:nth-child(2) {
|
||||
background-image: glyph("monospace", 1em, "2");
|
||||
}
|
||||
|
||||
ol > li:nth-child(3) {
|
||||
background-image: glyph("monospace", 1em, "3");
|
||||
}
|
||||
|
||||
ol > li:nth-child(4) {
|
||||
background-image: glyph("monospace", 1em, "4");
|
||||
}
|
||||
|
||||
ol > li:nth-child(5) {
|
||||
background-image: glyph("monospace", 1em, "5");
|
||||
}
|
||||
|
||||
ol > li:nth-child(6) {
|
||||
background-image: glyph("monospace", 1em, "6");
|
||||
}
|
||||
|
||||
ol > li:nth-child(7) {
|
||||
background-image: glyph("monospace", 1em, "7");
|
||||
}
|
||||
|
||||
ol > li:nth-child(8) {
|
||||
background-image: glyph("monospace", 1em, "8");
|
||||
}
|
||||
|
||||
ol > li:nth-child(9) {
|
||||
background-image: glyph("monospace", 1em, "9");
|
||||
}
|
||||
|
||||
ul > li {
|
||||
background-image: url("data:image/svg,<svg viewBox='0 0 24 24' width='12' height='12' fill='#ffffff'><path d='M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z'></path></svg>");
|
||||
background-tint: var(--font);
|
||||
background-position: 0.6em 0.45em;
|
||||
background-size: 0.5em 0.5em;
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
a {
|
||||
|
||||
@@ -247,6 +247,9 @@ enum class PropertyId : Uint32 {
|
||||
Bottom = String::hash( "bottom" ),
|
||||
Left = String::hash( "left" ),
|
||||
ZIndex = String::hash( "z-index" ),
|
||||
ListStyleType = String::hash( "list-style-type" ),
|
||||
ListStylePosition = String::hash( "list-style-position" ),
|
||||
ListStyleImage = String::hash( "list-style-image" ),
|
||||
DataLanguage = String::hash( "data-language" ), // Minor hack
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,32 @@ struct CSSPositionHelper {
|
||||
static CSSPosition fromString( std::string_view val );
|
||||
};
|
||||
|
||||
enum class CSSListStyleType {
|
||||
None,
|
||||
Disc,
|
||||
Circle,
|
||||
Square,
|
||||
Decimal,
|
||||
LowerAlpha,
|
||||
UpperAlpha,
|
||||
LowerRoman,
|
||||
UpperRoman
|
||||
};
|
||||
|
||||
struct CSSListStyleTypeHelper {
|
||||
static std::string toString( CSSListStyleType type );
|
||||
|
||||
static CSSListStyleType fromString( std::string_view val );
|
||||
};
|
||||
|
||||
enum class CSSListStylePosition { Outside, Inside };
|
||||
|
||||
struct CSSListStylePositionHelper {
|
||||
static std::string toString( CSSListStylePosition pos );
|
||||
|
||||
static CSSListStylePosition fromString( std::string_view val );
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif
|
||||
|
||||
@@ -128,6 +128,7 @@ enum UINodeType {
|
||||
UI_TYPE_BR,
|
||||
UI_TYPE_HTML_HTML,
|
||||
UI_TYPE_HTML_BODY,
|
||||
UI_TYPE_HTML_LIST_ITEM,
|
||||
UI_TYPE_MODULES = 10000,
|
||||
UI_TYPE_TERMINAL = 10001,
|
||||
UI_TYPE_USER = 200000,
|
||||
|
||||
51
include/eepp/ui/uihtmllistitem.hpp
Normal file
51
include/eepp/ui/uihtmllistitem.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef EE_UI_UIHTMLLISTITEM_HPP
|
||||
#define EE_UI_UIHTMLLISTITEM_HPP
|
||||
|
||||
#include <eepp/graphics/text.hpp>
|
||||
#include <eepp/ui/uirichtext.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
class EE_API UIHTMLListItem : public UIRichText {
|
||||
public:
|
||||
static UIHTMLListItem* New();
|
||||
|
||||
virtual Uint32 getType() const;
|
||||
|
||||
virtual bool isType( const Uint32& type ) const;
|
||||
|
||||
virtual void draw();
|
||||
|
||||
virtual bool applyProperty( const StyleSheetProperty& attribute );
|
||||
|
||||
virtual std::string getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex = 0 ) const;
|
||||
|
||||
virtual std::vector<PropertyId> getPropertiesImplemented() const;
|
||||
|
||||
CSSListStyleType getListStyleType() const { return mListStyleType; }
|
||||
|
||||
void setListStyleType( CSSListStyleType type );
|
||||
|
||||
CSSListStylePosition getListStylePosition() const { return mListStylePosition; }
|
||||
|
||||
void setListStylePosition( CSSListStylePosition pos );
|
||||
|
||||
protected:
|
||||
UIHTMLListItem();
|
||||
|
||||
CSSListStyleType mListStyleType{ CSSListStyleType::None };
|
||||
CSSListStylePosition mListStylePosition{ CSSListStylePosition::Outside };
|
||||
std::unique_ptr<Graphics::Text> mListMarkerText;
|
||||
|
||||
int countPrecedingLiSiblings() const;
|
||||
|
||||
String::View getListMarkerString() const;
|
||||
|
||||
void invalidateList();
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif
|
||||
@@ -44,8 +44,6 @@ class EE_API UIRichText : public UIHTMLWidget {
|
||||
|
||||
static UIRichText* NewPre() { return UIRichText::NewWithTag( "pre" ); };
|
||||
|
||||
static UIRichText* NewListItem() { return UIRichText::NewWithTag( "li" ); };
|
||||
|
||||
static UIRichText* NewBlockquote() { return UIRichText::NewWithTag( "blockquote" ); };
|
||||
|
||||
virtual Uint32 getType() const;
|
||||
|
||||
@@ -85,4 +85,58 @@ CSSPosition CSSPositionHelper::fromString( std::string_view val ) {
|
||||
return position;
|
||||
}
|
||||
|
||||
std::string CSSListStyleTypeHelper::toString( CSSListStyleType type ) {
|
||||
switch ( type ) {
|
||||
case CSSListStyleType::Disc:
|
||||
return "disc";
|
||||
case CSSListStyleType::Circle:
|
||||
return "circle";
|
||||
case CSSListStyleType::Square:
|
||||
return "square";
|
||||
case CSSListStyleType::Decimal:
|
||||
return "decimal";
|
||||
case CSSListStyleType::LowerAlpha:
|
||||
return "lower-alpha";
|
||||
case CSSListStyleType::UpperAlpha:
|
||||
return "upper-alpha";
|
||||
case CSSListStyleType::LowerRoman:
|
||||
return "lower-roman";
|
||||
case CSSListStyleType::UpperRoman:
|
||||
return "upper-roman";
|
||||
case CSSListStyleType::None:
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
CSSListStyleType CSSListStyleTypeHelper::fromString( std::string_view val ) {
|
||||
if ( val == "disc" )
|
||||
return CSSListStyleType::Disc;
|
||||
if ( val == "circle" )
|
||||
return CSSListStyleType::Circle;
|
||||
if ( val == "square" )
|
||||
return CSSListStyleType::Square;
|
||||
if ( val == "decimal" )
|
||||
return CSSListStyleType::Decimal;
|
||||
if ( val == "lower-alpha" )
|
||||
return CSSListStyleType::LowerAlpha;
|
||||
if ( val == "upper-alpha" )
|
||||
return CSSListStyleType::UpperAlpha;
|
||||
if ( val == "lower-roman" )
|
||||
return CSSListStyleType::LowerRoman;
|
||||
if ( val == "upper-roman" )
|
||||
return CSSListStyleType::UpperRoman;
|
||||
return CSSListStyleType::None;
|
||||
}
|
||||
|
||||
std::string CSSListStylePositionHelper::toString( CSSListStylePosition pos ) {
|
||||
return pos == CSSListStylePosition::Inside ? "inside" : "outside";
|
||||
}
|
||||
|
||||
CSSListStylePosition CSSListStylePositionHelper::fromString( std::string_view val ) {
|
||||
if ( val == "inside" )
|
||||
return CSSListStylePosition::Inside;
|
||||
return CSSListStylePosition::Outside;
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -428,6 +428,9 @@ void StyleSheetSpecification::registerDefaultProperties() {
|
||||
registerProperty( "hidden", "" ).setType( PropertyType::Bool );
|
||||
registerProperty( "display", "inline" ).setType( PropertyType::String );
|
||||
registerProperty( "position", "static" ).setType( PropertyType::String );
|
||||
registerProperty( "list-style-type", "none", true ).setType( PropertyType::String );
|
||||
registerProperty( "list-style-position", "outside", true ).setType( PropertyType::String );
|
||||
registerProperty( "list-style-image", "none" ).setType( PropertyType::String );
|
||||
registerProperty( "top", "auto" ).setType( PropertyType::NumberLength );
|
||||
registerProperty( "right", "auto" ).setType( PropertyType::NumberLength );
|
||||
registerProperty( "bottom", "auto" ).setType( PropertyType::NumberLength );
|
||||
@@ -516,6 +519,9 @@ void StyleSheetSpecification::registerDefaultProperties() {
|
||||
registerShorthand( "border-bottom",
|
||||
{ "border-bottom-width", "border-bottom-style", "border-bottom-color" },
|
||||
"border-side" );
|
||||
registerShorthand( "list-style",
|
||||
{ "list-style-type", "list-style-position", "list-style-image" },
|
||||
"list-style" );
|
||||
}
|
||||
|
||||
void StyleSheetSpecification::registerNodeSelector( const std::string& name,
|
||||
@@ -1135,6 +1141,40 @@ void StyleSheetSpecification::registerDefaultShorthandParsers() {
|
||||
|
||||
return properties;
|
||||
};
|
||||
|
||||
mShorthandParsers["list-style"] = []( const ShorthandDefinition* shorthand,
|
||||
std::string value ) -> std::vector<StyleSheetProperty> {
|
||||
value = String::trim( value );
|
||||
if ( value.empty() )
|
||||
return {};
|
||||
std::vector<StyleSheetProperty> properties;
|
||||
const std::vector<std::string>& propNames = shorthand->getProperties();
|
||||
if ( propNames.empty() )
|
||||
return {};
|
||||
auto tokens = String::split( value, " ", "", "(" );
|
||||
int typePos = getIndexEndingWith( propNames, "-type" );
|
||||
int posPos = getIndexEndingWith( propNames, "-position" );
|
||||
int imagePos = getIndexEndingWith( propNames, "-image" );
|
||||
for ( auto& tok : tokens ) {
|
||||
String::trimInPlace( tok );
|
||||
if ( tok == "inside" || tok == "outside" ) {
|
||||
if ( posPos != -1 )
|
||||
properties.emplace_back( StyleSheetProperty( propNames[posPos], tok ) );
|
||||
} else if ( String::startsWith( tok, "url(" ) ) {
|
||||
if ( imagePos != -1 )
|
||||
properties.emplace_back( StyleSheetProperty( propNames[imagePos], tok ) );
|
||||
} else if ( tok == "none" ) {
|
||||
if ( typePos != -1 )
|
||||
properties.emplace_back( StyleSheetProperty( propNames[typePos], tok ) );
|
||||
if ( imagePos != -1 )
|
||||
properties.emplace_back( StyleSheetProperty( propNames[imagePos], tok ) );
|
||||
} else {
|
||||
if ( typePos != -1 )
|
||||
properties.emplace_back( StyleSheetProperty( propNames[typePos], tok ) );
|
||||
}
|
||||
}
|
||||
return properties;
|
||||
};
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::CSS
|
||||
|
||||
198
src/eepp/ui/uihtmllistitem.cpp
Normal file
198
src/eepp/ui/uihtmllistitem.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
#include <eepp/graphics/primitives.hpp>
|
||||
#include <eepp/ui/css/propertydefinition.hpp>
|
||||
#include <eepp/ui/uihtmllistitem.hpp>
|
||||
#include <eepp/ui/uilayouter.hpp>
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
UIHTMLListItem* UIHTMLListItem::New() {
|
||||
return eeNew( UIHTMLListItem, () );
|
||||
}
|
||||
|
||||
UIHTMLListItem::UIHTMLListItem() : UIRichText( "li" ) {}
|
||||
|
||||
void UIHTMLListItem::setListStyleType( CSSListStyleType type ) {
|
||||
if ( mListStyleType != type ) {
|
||||
mListStyleType = type;
|
||||
invalidateList();
|
||||
}
|
||||
}
|
||||
|
||||
void UIHTMLListItem::setListStylePosition( CSSListStylePosition pos ) {
|
||||
if ( mListStylePosition != pos ) {
|
||||
mListStylePosition = pos;
|
||||
invalidateList();
|
||||
}
|
||||
}
|
||||
|
||||
Uint32 UIHTMLListItem::getType() const {
|
||||
return UI_TYPE_HTML_LIST_ITEM;
|
||||
}
|
||||
|
||||
bool UIHTMLListItem::isType( const Uint32& type ) const {
|
||||
return UIHTMLListItem::getType() == type ? true : UIRichText::isType( type );
|
||||
}
|
||||
|
||||
void UIHTMLListItem::draw() {
|
||||
UIRichText::draw();
|
||||
if ( mVisible && 0.f != mAlpha ) {
|
||||
const FontStyleConfig& style = mRichText.getFontStyleConfig();
|
||||
Float fontSize = style.CharacterSize;
|
||||
Float offset = 0.25f * fontSize;
|
||||
Float lineHeight =
|
||||
style.Font ? style.Font->getLineSpacing( (unsigned int)fontSize ) : fontSize;
|
||||
Float lineTop = mScreenPos.y + mPaddingPx.Top;
|
||||
|
||||
if ( mListStyleType == CSSListStyleType::Disc ) {
|
||||
Float radius = fontSize * 0.22f;
|
||||
Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - radius * 2.f - offset );
|
||||
Float markerY = std::floor( lineTop + ( lineHeight - radius * 2.f ) * 0.5f + radius );
|
||||
Primitives p;
|
||||
p.setColor( style.FontColor );
|
||||
p.setFillMode( PrimitiveFillMode::DRAW_FILL );
|
||||
p.drawCircle( { markerX, markerY }, radius );
|
||||
} else if ( mListStyleType == CSSListStyleType::Circle ) {
|
||||
Float radius = fontSize * 0.2f;
|
||||
Float lineWidth = fontSize * 0.04f;
|
||||
Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - radius * 2.f - offset );
|
||||
Float markerY = std::floor( lineTop + ( lineHeight - radius * 2.f ) * 0.5f + radius );
|
||||
Primitives p;
|
||||
p.setColor( style.FontColor );
|
||||
p.setFillMode( PrimitiveFillMode::DRAW_LINE );
|
||||
p.setLineWidth( lineWidth );
|
||||
p.drawCircle( { markerX, markerY }, radius );
|
||||
} else if ( mListStyleType == CSSListStyleType::Square ) {
|
||||
Float size = fontSize * 0.38f;
|
||||
Float markerX = std::floor( mScreenPos.x + mPaddingPx.Left - size - fontSize * 0.5 );
|
||||
Float markerY = std::floor( lineTop + ( lineHeight - size ) * 0.5f );
|
||||
Primitives p;
|
||||
p.setColor( style.FontColor );
|
||||
p.setFillMode( PrimitiveFillMode::DRAW_FILL );
|
||||
p.drawRectangle( Rectf( markerX, markerY, markerX + size, markerY + size ) );
|
||||
} else if ( mListMarkerText && !mListMarkerText->getString().empty() ) {
|
||||
Float markerX =
|
||||
mScreenPos.x + mPaddingPx.Left - mListMarkerText->getTextWidth() - offset;
|
||||
mListMarkerText->draw( markerX, lineTop, Vector2f::One, 0.f, getBlendMode() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UIHTMLListItem::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
if ( !checkPropertyDefinition( attribute ) )
|
||||
return false;
|
||||
|
||||
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
|
||||
case PropertyId::ListStyleType:
|
||||
setListStyleType( CSSListStyleTypeHelper::fromString( attribute.value() ) );
|
||||
return true;
|
||||
case PropertyId::ListStylePosition:
|
||||
setListStylePosition( CSSListStylePositionHelper::fromString( attribute.value() ) );
|
||||
return true;
|
||||
default:
|
||||
return UIRichText::applyProperty( attribute );
|
||||
}
|
||||
}
|
||||
|
||||
std::string UIHTMLListItem::getPropertyString( const PropertyDefinition* propertyDef,
|
||||
const Uint32& propertyIndex ) const {
|
||||
if ( NULL == propertyDef )
|
||||
return "";
|
||||
|
||||
switch ( propertyDef->getPropertyId() ) {
|
||||
case PropertyId::ListStyleType:
|
||||
return CSSListStyleTypeHelper::toString( mListStyleType );
|
||||
case PropertyId::ListStylePosition:
|
||||
return CSSListStylePositionHelper::toString( mListStylePosition );
|
||||
default:
|
||||
return UIRichText::getPropertyString( propertyDef, propertyIndex );
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<PropertyId> UIHTMLListItem::getPropertiesImplemented() const {
|
||||
auto props = UIRichText::getPropertiesImplemented();
|
||||
props.push_back( PropertyId::ListStyleType );
|
||||
props.push_back( PropertyId::ListStylePosition );
|
||||
return props;
|
||||
}
|
||||
|
||||
void UIHTMLListItem::invalidateList() {
|
||||
if ( mListStyleType == CSSListStyleType::None || mListStyleType == CSSListStyleType::Disc ||
|
||||
mListStyleType == CSSListStyleType::Circle ||
|
||||
mListStyleType == CSSListStyleType::Square ) {
|
||||
mListMarkerText.reset();
|
||||
} else {
|
||||
String::View markerStr = getListMarkerString();
|
||||
if ( !markerStr.empty() ) {
|
||||
if ( !mListMarkerText )
|
||||
mListMarkerText = std::make_unique<Text>();
|
||||
mListMarkerText->setString( markerStr );
|
||||
mListMarkerText->setStyleConfig( mRichText.getFontStyleConfig() );
|
||||
} else {
|
||||
mListMarkerText.reset();
|
||||
}
|
||||
}
|
||||
invalidateDraw();
|
||||
}
|
||||
|
||||
int UIHTMLListItem::countPrecedingLiSiblings() const {
|
||||
int count = 0;
|
||||
Node* prev = getPrevNode();
|
||||
while ( prev ) {
|
||||
if ( prev->isWidget() && prev->asType<UIWidget>()->getElementTag() == "li" )
|
||||
count++;
|
||||
prev = prev->getPrevNode();
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
String::View UIHTMLListItem::getListMarkerString() const {
|
||||
static String sBuf;
|
||||
|
||||
switch ( mListStyleType ) {
|
||||
case CSSListStyleType::None:
|
||||
case CSSListStyleType::Disc:
|
||||
case CSSListStyleType::Circle:
|
||||
case CSSListStyleType::Square:
|
||||
return {};
|
||||
case CSSListStyleType::Decimal: {
|
||||
int idx = countPrecedingLiSiblings() + 1;
|
||||
sBuf = String( String::toString( idx ) + ". " );
|
||||
return sBuf.view();
|
||||
}
|
||||
case CSSListStyleType::LowerAlpha: {
|
||||
int idx = countPrecedingLiSiblings();
|
||||
char c = 'a' + ( idx % 26 );
|
||||
sBuf = String( 1, (String::StringBaseType)c ) + ". ";
|
||||
return sBuf.view();
|
||||
}
|
||||
case CSSListStyleType::UpperAlpha: {
|
||||
int idx = countPrecedingLiSiblings();
|
||||
char c = 'A' + ( idx % 26 );
|
||||
sBuf = String( 1, (String::StringBaseType)c ) + ". ";
|
||||
return sBuf.view();
|
||||
}
|
||||
case CSSListStyleType::LowerRoman: {
|
||||
static const char* numerals[] = { "i", "ii", "iii", "iv", "v", "vi",
|
||||
"vii", "viii", "ix", "x", "xi", "xii" };
|
||||
int idx = countPrecedingLiSiblings();
|
||||
if ( idx < 12 )
|
||||
sBuf = String( numerals[idx] ) + ". ";
|
||||
else
|
||||
sBuf = String( String::toString( idx + 1 ) + ". " );
|
||||
return sBuf.view();
|
||||
}
|
||||
case CSSListStyleType::UpperRoman: {
|
||||
static const char* numerals[] = { "I", "II", "III", "IV", "V", "VI",
|
||||
"VII", "VIII", "IX", "X", "XI", "XII" };
|
||||
int idx = countPrecedingLiSiblings();
|
||||
if ( idx < 12 )
|
||||
sBuf = String( numerals[idx] ) + ". ";
|
||||
else
|
||||
sBuf = String( String::toString( idx + 1 ) + ". " );
|
||||
return sBuf.view();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}} // namespace EE::UI
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <eepp/ui/uidropdownlist.hpp>
|
||||
#include <eepp/ui/uidropdownmodellist.hpp>
|
||||
#include <eepp/ui/uigridlayout.hpp>
|
||||
#include <eepp/ui/uihtmllistitem.hpp>
|
||||
#include <eepp/ui/uihtmltable.hpp>
|
||||
#include <eepp/ui/uiimage.hpp>
|
||||
#include <eepp/ui/uilinearlayout.hpp>
|
||||
@@ -158,7 +159,7 @@ void UIWidgetCreator::createBaseWidgetList() {
|
||||
registeredWidget["hr"] = UIRichText::NewHr;
|
||||
registeredWidget["ul"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ul" ); };
|
||||
registeredWidget["ol"] = [] { return UILinearLayout::NewVerticalWidthMatchParent( "ol" ); };
|
||||
registeredWidget["li"] = UIRichText::NewListItem;
|
||||
registeredWidget["li"] = UIHTMLListItem::New;
|
||||
registeredWidget["pre"] = UIRichText::NewPre;
|
||||
registeredWidget["img"] = [] {
|
||||
auto img = UIImage::NewWithTag( "img" );
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/sys.hpp>
|
||||
#include <eepp/ui/css/stylesheetparser.hpp>
|
||||
#include <eepp/ui/css/stylesheetspecification.hpp>
|
||||
#include <eepp/ui/htmlinput.hpp>
|
||||
#include <eepp/ui/htmltextarea.hpp>
|
||||
#include <eepp/ui/htmltextinput.hpp>
|
||||
@@ -570,3 +571,157 @@ UTEST( UILayout, marginAuto ) {
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UILayout, listStyleTypeDecimal ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<html>
|
||||
<ol>
|
||||
<li id="li1" style="list-style-type: decimal;">First item</li>
|
||||
<li id="li2" style="list-style-type: decimal;">Second item</li>
|
||||
<li id="li3" style="list-style-type: decimal;">Third item</li>
|
||||
</ol>
|
||||
</html>
|
||||
)html" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* propDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
ASSERT_TRUE( propDef != nullptr );
|
||||
|
||||
auto* li1 = sceneNode->getRoot()->find( "li1" )->asType<UIRichText>();
|
||||
auto* li2 = sceneNode->getRoot()->find( "li2" )->asType<UIRichText>();
|
||||
auto* li3 = sceneNode->getRoot()->find( "li3" )->asType<UIRichText>();
|
||||
|
||||
ASSERT_TRUE( li1 != nullptr );
|
||||
ASSERT_TRUE( li2 != nullptr );
|
||||
ASSERT_TRUE( li3 != nullptr );
|
||||
|
||||
EXPECT_TRUE( li1->getPropertyString( propDef ) == "decimal" );
|
||||
EXPECT_TRUE( li2->getPropertyString( propDef ) == "decimal" );
|
||||
EXPECT_TRUE( li3->getPropertyString( propDef ) == "decimal" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UILayout, listStyleTypeDisc ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<html>
|
||||
<ul>
|
||||
<li id="li1" style="list-style-type: disc;">Bullet item</li>
|
||||
</ul>
|
||||
</html>
|
||||
)html" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* propDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
ASSERT_TRUE( propDef != nullptr );
|
||||
|
||||
auto* li1 = sceneNode->getRoot()->find( "li1" )->asType<UIRichText>();
|
||||
ASSERT_TRUE( li1 != nullptr );
|
||||
|
||||
EXPECT_TRUE( li1->getPropertyString( propDef ) == "disc" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UILayout, listStyleShorthand ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<html>
|
||||
<ol>
|
||||
<li id="li1" style="list-style: decimal outside;">First</li>
|
||||
<li id="li2" style="list-style: lower-alpha inside;">Second</li>
|
||||
<li id="li3" style="list-style: none;">Third</li>
|
||||
</ol>
|
||||
<ul>
|
||||
<li id="li4" style="list-style: disc;">Bullet</li>
|
||||
<li id="li5" style="list-style: square outside;">Square</li>
|
||||
<li id="li6" style="list-style: circle;">Circle</li>
|
||||
</ul>
|
||||
</html>
|
||||
)html" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* typeDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
const auto* posDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-position" );
|
||||
|
||||
for ( const char* id : { "li1", "li2", "li3", "li4", "li5", "li6" } ) {
|
||||
auto* li = sceneNode->getRoot()->find( id )->asType<UIWidget>();
|
||||
ASSERT_TRUE( li != nullptr );
|
||||
EXPECT_TRUE( li->isType( UI_TYPE_HTML_LIST_ITEM ) );
|
||||
}
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "decimal" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li1" )->asType<UIRichText>()->getPropertyString( posDef ) == "outside" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString( typeDef ) == "lower-alpha" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li2" )->asType<UIRichText>()->getPropertyString( posDef ) == "inside" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li3" )->asType<UIRichText>()->getPropertyString( typeDef ) == "none" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li4" )->asType<UIRichText>()->getPropertyString( typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString( typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li5" )->asType<UIRichText>()->getPropertyString( posDef ) == "outside" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "li6" )->asType<UIRichText>()->getPropertyString( typeDef ) == "circle" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UILayout, listStyleInheritanceFromUl ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
ul.a { list-style-type: circle; }
|
||||
ul.b { list-style-type: disc; }
|
||||
ul.c { list-style-type: square; }
|
||||
ol.d { list-style-type: decimal; }
|
||||
ol.h { list-style-type: upper-roman; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ol class="h">
|
||||
<li id="h1">Coffee</li>
|
||||
</ol>
|
||||
<ul class="a">
|
||||
<li id="a1">Coffee</li>
|
||||
</ul>
|
||||
<ul class="b">
|
||||
<li id="b1">Coffee</li>
|
||||
</ul>
|
||||
<ul class="c">
|
||||
<li id="c1">Coffee</li>
|
||||
</ul>
|
||||
<ol class="d">
|
||||
<li id="d1">Coffee</li>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
)html" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
const auto* typeDef =
|
||||
StyleSheetSpecification::instance()->getProperty( "list-style-type" );
|
||||
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "h1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "upper-roman" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "a1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "circle" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "b1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "disc" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "c1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "square" );
|
||||
EXPECT_TRUE( sceneNode->getRoot()->find( "d1" )->asType<UIRichText>()->getPropertyString( typeDef ) == "decimal" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user