Skip to content

Commit 2fe55e7

Browse files
Unix4everArtem Chernyshev
andauthored
Fix several small issues (#19)
1. If using component without window it may lead to wrong layout. 2. CSS chain was not working for components nested into components. 3. Style scale was not passed to child contexts. 4. Implement number input type. 5. Fix absolute positioning (wasn't handling scroll correctly). Co-authored-by: Artem Chernyshev <[email protected]>
1 parent 14a99bd commit 2fe55e7

File tree

9 files changed

+143
-10
lines changed

9 files changed

+143
-10
lines changed

samples/simple/styled.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
margin-bottom: 2px;
137137
}
138138

139-
input[type="text"], input[type="password"] {
139+
input[type="text"], input[type="password"], input[type="number"] {
140140
display: block;
141141
padding: 0.2em 0.5em;
142142
margin: 2px 2px 10px 2px;
@@ -145,7 +145,7 @@
145145
background-color: #222222;
146146
}
147147

148-
input[type="text"]:active, input[type="password"]:active {
148+
input[type="text"]:active, input[type="password"]:active, input[type="number"]:active {
149149
margin-top: 0px;
150150
margin-left: 0px;
151151
margin-right: 0px;
@@ -244,6 +244,10 @@
244244
<span>
245245
<input type="range" style="display: inline-block; width: 50%" min="0" max="20" step="0.1" v-model="slide"/>
246246
</span>
247+
<label>Number input:</label>
248+
<span>
249+
<input type="number" style="display: inline-block; width: 50%" min="0" max="20" step="0.1" v-model="slide"/>
250+
</span>
247251
<label>Checkboxes sharing the same model:</label>
248252
<input style="margin-right: 0.2rem; margin-top: 0.2rem; display: block" type="checkbox" value="first checkbox" v-model="arr"/>
249253
<input style="margin-right: 0.2rem; margin-top: 0.2rem; display: block" type="checkbox" value="second checkbox" v-model="arr"/>

src/extras/xhtml.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ namespace ImVue {
210210
, max(100.0f)
211211
, step(1.0f)
212212
, name(0)
213+
, speed(1.0f)
213214
, mValue(0)
214215
, mModel(0)
215216
, mValueUpdated(false)
@@ -377,6 +378,10 @@ namespace ImVue {
377378
break;
378379
case RANGE:
379380
changed = ImGui::SliderFloat(placeholder ? placeholder : "##slider", &mSliderValue, min, max, format ? format : "%.3f", step);
381+
break;
382+
case NUMBER:
383+
changed = ImGui::DragFloat(placeholder ? placeholder : "##dragfloat", &mSliderValue, speed, min, max, format ? format : "%.3f", step);
384+
break;
380385
default:
381386
// nothing
382387
break;
@@ -427,6 +432,8 @@ namespace ImVue {
427432
mType = RADIO;
428433
} else if(ImStricmp(type, "range") == 0) {
429434
mType = RANGE;
435+
} else if(ImStricmp(type, "number") == 0) {
436+
mType = NUMBER;
430437
}
431438

432439
if(mType == TEXT || mType == PASSWORD) {
@@ -487,6 +494,8 @@ namespace ImVue {
487494
// radio only
488495
char* name;
489496

497+
// number only
498+
float speed;
490499
private:
491500

492501
void syncModel(bool write = false)
@@ -515,6 +524,7 @@ namespace ImVue {
515524
case RADIO:
516525
(*mScriptState)[mModel] = mValue ? mValue : placeholder;
517526
break;
527+
case NUMBER:
518528
case RANGE:
519529
(*mScriptState)[mModel] = mSliderValue;
520530
default:
@@ -553,6 +563,7 @@ namespace ImVue {
553563
resetState(CHECKED);
554564

555565
break;
566+
case NUMBER:
556567
case RANGE:
557568
mSliderValue = object.as<float>();
558569
default:
@@ -619,6 +630,7 @@ namespace ImVue {
619630
.attribute("max", &Input::max)
620631
.attribute("step", &Input::step)
621632
.attribute("format", &Input::format)
633+
.attribute("speed", &Input::speed)
622634
.attribute("placeholder", &Input::placeholder);
623635
}
624636

src/imvue.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ namespace ImVue {
197197
res = builder->create(node, ctx, sctx, parent);
198198
} else {
199199
// then try to create a component
200-
res = createComponent(node, ctx, sctx);
200+
res = createComponent(node, ctx, sctx, parent);
201201
}
202202

203203
if(res && sctx) {
@@ -206,7 +206,7 @@ namespace ImVue {
206206
return res;
207207
}
208208

209-
Element* ComponentContainer::createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx)
209+
Element* ComponentContainer::createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx, Element* parent)
210210
{
211211
ImU32 nodeID = ImHashStr(node->name());
212212
if(mComponents.count(nodeID) == 0) {
@@ -215,7 +215,7 @@ namespace ImVue {
215215

216216
Component* component = mComponents[nodeID].create();
217217
try {
218-
component->configure(node, ctx, sctx, this);
218+
component->configure(node, ctx, sctx, parent);
219219
} catch(...) {
220220
delete component;
221221
throw;
@@ -343,7 +343,7 @@ namespace ImVue {
343343
, mData(data)
344344
{
345345
parseXML(tmpl.get());
346-
mFlags = mFlags | Element::COMPONENT;
346+
mFlags = mFlags | Element::COMPONENT | Element::PSEUDO_ELEMENT;
347347
}
348348

349349
Component::~Component()

src/imvue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ namespace ImVue {
150150
/**
151151
* Creates component
152152
*/
153-
Element* createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx);
153+
Element* createComponent(rapidxml::xml_node<>* node, Context* ctx, ScriptState::Context* sctx, Element* parent);
154154

155155
void parseXML(const char* data);
156156

src/imvue_context.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ namespace ImVue {
195195
Style* style = new Style(ctx->style);
196196
Context* child = createContext(ctx->factory, script, ctx->texture, ctx->fs, ctx->fontManager, style, ctx->userdata);
197197
child->parent = ctx;
198+
child->scale = ctx->scale;
198199
return child;
199200
}
200201
}

src/imvue_style.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,7 @@ namespace ImVue {
530530
} else {
531531
pos = window->Pos;
532532
}
533+
pos -= window->Scroll;
533534
break;
534535
}
535536
case CSS_POSITION_FIXED:
@@ -1054,7 +1055,7 @@ namespace ImVue {
10541055
ImGuiWindow* window = GetCurrentWindowNoDefault();
10551056
if(window){
10561057
Element* parent = e->getParent();
1057-
while(parent && parent->display == CSS_DISPLAY_INLINE) {
1058+
while(parent && (parent->display == CSS_DISPLAY_INLINE || (parent->getFlags() & Element::PSEUDO_ELEMENT) != 0)) {
10581059
parent = parent->getParent();
10591060
}
10601061

@@ -1348,8 +1349,6 @@ namespace ImVue {
13481349
if (code != CSS_OK)
13491350
IMVUE_EXCEPTION(StyleError, "failed to append base stylesheet: %s", css_error_to_string(code));
13501351

1351-
if(mParent)
1352-
mParent->appendSheets(ctx, false);
13531352
appendSheets(ctx, true);
13541353
return ctx;
13551354
}
@@ -1369,6 +1368,10 @@ namespace ImVue {
13691368

13701369
void Style::appendSheets(css_select_ctx* ctx, bool scoped)
13711370
{
1371+
if(mParent) {
1372+
mParent->appendSheets(ctx, false);
1373+
}
1374+
13721375
for(int i = 0; i < mSheets.size(); ++i) {
13731376
if(mSheets[i].scoped && !scoped) {
13741377
continue;

tests/resources/dimensions.imv

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<template>
2+
<div style="width: 100%; height: 100%" id="check"/>
3+
</template>
4+
5+
<script>
6+
return {}
7+
</script>

tests/resources/dimensions.xml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<style>
2+
.test {
3+
position: absolute;
4+
top: 5px;
5+
left: 5px;
6+
width: 300px;
7+
height: 300px;
8+
padding: 0;
9+
margin: 0;
10+
}
11+
</style>
12+
13+
<template>
14+
<window name="test" class="test" :flags="ImGuiWindowFlags_NoTitleBar">
15+
<dimensions-test/>
16+
</window>
17+
</template>
18+
19+
<script>
20+
return ImVue.new({
21+
components = {
22+
['dimensions-test'] = require 'dimensions'
23+
}
24+
})
25+
</script>

tests/unit/style.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "imvue_generated.h"
55
#include "imvue_errors.h"
66
#include "utils.h"
7+
#include "extras/xhtml.h"
78

89
#if defined(WITH_LUA)
910
#include "lua/script.h"
@@ -760,3 +761,83 @@ INSTANTIATE_TEST_CASE_P(
760761
#endif
761762
));
762763

764+
#if defined(WITH_LUA)
765+
766+
class TestStylesComponents : public ::testing::Test {
767+
768+
public:
769+
770+
TestStylesComponents()
771+
: mDoc(0)
772+
{
773+
}
774+
775+
~TestStylesComponents()
776+
{
777+
if(mDoc) {
778+
delete mDoc;
779+
mDoc = 0;
780+
}
781+
}
782+
783+
void SetUp() override
784+
{
785+
L = luaL_newstate();
786+
luaL_openlibs(L);
787+
ImVue::registerBindings(L);
788+
}
789+
790+
void TearDown() override
791+
{
792+
if(mDoc) {
793+
delete mDoc;
794+
mDoc = 0;
795+
}
796+
lua_close(L);
797+
}
798+
799+
ImVue::Document& createDoc(const char* path)
800+
{
801+
if(mDoc) {
802+
delete mDoc;
803+
}
804+
805+
ImVue::ElementFactory* factory = ImVue::createElementFactory();
806+
factory->element<TestElement>("test");
807+
808+
ImVue::Context* ctx = ImVue::createContext(factory, new ImVue::LuaScriptState(L));
809+
ImVue::Document doc(ctx);
810+
char* data = ctx->fs->load(path);
811+
try {
812+
mDoc = new ImVue::Document(ctx);
813+
mDoc->parse(data);
814+
} catch(...) {
815+
delete mDoc;
816+
ImGui::MemFree(data);
817+
throw;
818+
}
819+
ImGui::MemFree(data);
820+
821+
return *mDoc;
822+
}
823+
824+
private:
825+
ImVue::Document* mDoc;
826+
lua_State* L;
827+
};
828+
829+
TEST_F(TestStylesComponents, Dimensions)
830+
{
831+
ImVue::Document& d = createDoc("dimensions.xml");
832+
ImVector<ImVue::HtmlContainer*> els = d.getChildren<ImVue::HtmlContainer>("#check", true);
833+
834+
ASSERT_GT(els.size(), 0);
835+
836+
renderDocument(d);
837+
838+
ImVue::HtmlContainer* div = els[0];
839+
EXPECT_EQ(div->computedSize.x, 300);
840+
EXPECT_EQ(div->computedSize.y, 300);
841+
}
842+
843+
#endif

0 commit comments

Comments
 (0)