diff --git a/samples/simple/styled.xml b/samples/simple/styled.xml index 62a6be7..2dc03f6 100644 --- a/samples/simple/styled.xml +++ b/samples/simple/styled.xml @@ -136,7 +136,7 @@ margin-bottom: 2px; } - input[type="text"], input[type="password"] { + input[type="text"], input[type="password"], input[type="number"] { display: block; padding: 0.2em 0.5em; margin: 2px 2px 10px 2px; @@ -145,7 +145,7 @@ background-color: #222222; } - input[type="text"]:active, input[type="password"]:active { + input[type="text"]:active, input[type="password"]:active, input[type="number"]:active { margin-top: 0px; margin-left: 0px; margin-right: 0px; @@ -244,6 +244,10 @@ + + + + diff --git a/src/extras/xhtml.h b/src/extras/xhtml.h index 57ea0f8..202bdd4 100644 --- a/src/extras/xhtml.h +++ b/src/extras/xhtml.h @@ -210,6 +210,7 @@ namespace ImVue { , max(100.0f) , step(1.0f) , name(0) + , speed(1.0f) , mValue(0) , mModel(0) , mValueUpdated(false) @@ -377,6 +378,10 @@ namespace ImVue { break; case RANGE: changed = ImGui::SliderFloat(placeholder ? placeholder : "##slider", &mSliderValue, min, max, format ? format : "%.3f", step); + break; + case NUMBER: + changed = ImGui::DragFloat(placeholder ? placeholder : "##dragfloat", &mSliderValue, speed, min, max, format ? format : "%.3f", step); + break; default: // nothing break; @@ -427,6 +432,8 @@ namespace ImVue { mType = RADIO; } else if(ImStricmp(type, "range") == 0) { mType = RANGE; + } else if(ImStricmp(type, "number") == 0) { + mType = NUMBER; } if(mType == TEXT || mType == PASSWORD) { @@ -487,6 +494,8 @@ namespace ImVue { // radio only char* name; + // number only + float speed; private: void syncModel(bool write = false) @@ -515,6 +524,7 @@ namespace ImVue { case RADIO: (*mScriptState)[mModel] = mValue ? mValue : placeholder; break; + case NUMBER: case RANGE: (*mScriptState)[mModel] = mSliderValue; default: @@ -553,6 +563,7 @@ namespace ImVue { resetState(CHECKED); break; + case NUMBER: case RANGE: mSliderValue = object.as(); default: @@ -619,6 +630,7 @@ namespace ImVue { .attribute("max", &Input::max) .attribute("step", &Input::step) .attribute("format", &Input::format) + .attribute("speed", &Input::speed) .attribute("placeholder", &Input::placeholder); } diff --git a/src/imvue.cpp b/src/imvue.cpp index 76edfa7..702fd7c 100644 --- a/src/imvue.cpp +++ b/src/imvue.cpp @@ -197,7 +197,7 @@ namespace ImVue { res = builder->create(node, ctx, sctx, parent); } else { // then try to create a component - res = createComponent(node, ctx, sctx); + res = createComponent(node, ctx, sctx, parent); } if(res && sctx) { @@ -206,7 +206,7 @@ namespace ImVue { return res; } - Element* ComponentContainer::createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx) + Element* ComponentContainer::createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx, Element* parent) { ImU32 nodeID = ImHashStr(node->name()); if(mComponents.count(nodeID) == 0) { @@ -215,7 +215,7 @@ namespace ImVue { Component* component = mComponents[nodeID].create(); try { - component->configure(node, ctx, sctx, this); + component->configure(node, ctx, sctx, parent); } catch(...) { delete component; throw; @@ -343,7 +343,7 @@ namespace ImVue { , mData(data) { parseXML(tmpl.get()); - mFlags = mFlags | Element::COMPONENT; + mFlags = mFlags | Element::COMPONENT | Element::PSEUDO_ELEMENT; } Component::~Component() diff --git a/src/imvue.h b/src/imvue.h index d176426..1399631 100644 --- a/src/imvue.h +++ b/src/imvue.h @@ -150,7 +150,7 @@ namespace ImVue { /** * Creates component */ - Element* createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx); + Element* createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx, Element* parent); void parseXML(const char* data); diff --git a/src/imvue_context.cpp b/src/imvue_context.cpp index ecaf8b8..46388bd 100644 --- a/src/imvue_context.cpp +++ b/src/imvue_context.cpp @@ -195,6 +195,7 @@ namespace ImVue { Style* style = new Style(ctx->style); Context* child = createContext(ctx->factory, script, ctx->texture, ctx->fs, ctx->fontManager, style, ctx->userdata); child->parent = ctx; + child->scale = ctx->scale; return child; } } diff --git a/src/imvue_style.cpp b/src/imvue_style.cpp index a29aee3..af47aba 100644 --- a/src/imvue_style.cpp +++ b/src/imvue_style.cpp @@ -530,6 +530,7 @@ namespace ImVue { } else { pos = window->Pos; } + pos -= window->Scroll; break; } case CSS_POSITION_FIXED: @@ -1054,7 +1055,7 @@ namespace ImVue { ImGuiWindow* window = GetCurrentWindowNoDefault(); if(window){ Element* parent = e->getParent(); - while(parent && parent->display == CSS_DISPLAY_INLINE) { + while(parent && (parent->display == CSS_DISPLAY_INLINE || (parent->getFlags() & Element::PSEUDO_ELEMENT) != 0)) { parent = parent->getParent(); } @@ -1348,8 +1349,6 @@ namespace ImVue { if (code != CSS_OK) IMVUE_EXCEPTION(StyleError, "failed to append base stylesheet: %s", css_error_to_string(code)); - if(mParent) - mParent->appendSheets(ctx, false); appendSheets(ctx, true); return ctx; } @@ -1369,6 +1368,10 @@ namespace ImVue { void Style::appendSheets(css_select_ctx* ctx, bool scoped) { + if(mParent) { + mParent->appendSheets(ctx, false); + } + for(int i = 0; i < mSheets.size(); ++i) { if(mSheets[i].scoped && !scoped) { continue; diff --git a/tests/resources/dimensions.imv b/tests/resources/dimensions.imv new file mode 100644 index 0000000..ae1bdbe --- /dev/null +++ b/tests/resources/dimensions.imv @@ -0,0 +1,7 @@ + + + diff --git a/tests/resources/dimensions.xml b/tests/resources/dimensions.xml new file mode 100644 index 0000000..4ec6156 --- /dev/null +++ b/tests/resources/dimensions.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/tests/unit/style.cpp b/tests/unit/style.cpp index 594569f..b3934b7 100644 --- a/tests/unit/style.cpp +++ b/tests/unit/style.cpp @@ -4,6 +4,7 @@ #include "imvue_generated.h" #include "imvue_errors.h" #include "utils.h" +#include "extras/xhtml.h" #if defined(WITH_LUA) #include "lua/script.h" @@ -760,3 +761,83 @@ INSTANTIATE_TEST_CASE_P( #endif )); +#if defined(WITH_LUA) + +class TestStylesComponents : public ::testing::Test { + + public: + + TestStylesComponents() + : mDoc(0) + { + } + + ~TestStylesComponents() + { + if(mDoc) { + delete mDoc; + mDoc = 0; + } + } + + void SetUp() override + { + L = luaL_newstate(); + luaL_openlibs(L); + ImVue::registerBindings(L); + } + + void TearDown() override + { + if(mDoc) { + delete mDoc; + mDoc = 0; + } + lua_close(L); + } + + ImVue::Document& createDoc(const char* path) + { + if(mDoc) { + delete mDoc; + } + + ImVue::ElementFactory* factory = ImVue::createElementFactory(); + factory->element("test"); + + ImVue::Context* ctx = ImVue::createContext(factory, new ImVue::LuaScriptState(L)); + ImVue::Document doc(ctx); + char* data = ctx->fs->load(path); + try { + mDoc = new ImVue::Document(ctx); + mDoc->parse(data); + } catch(...) { + delete mDoc; + ImGui::MemFree(data); + throw; + } + ImGui::MemFree(data); + + return *mDoc; + } + + private: + ImVue::Document* mDoc; + lua_State* L; +}; + +TEST_F(TestStylesComponents, Dimensions) +{ + ImVue::Document& d = createDoc("dimensions.xml"); + ImVector els = d.getChildren("#check", true); + + ASSERT_GT(els.size(), 0); + + renderDocument(d); + + ImVue::HtmlContainer* div = els[0]; + EXPECT_EQ(div->computedSize.x, 300); + EXPECT_EQ(div->computedSize.y, 300); +} + +#endif