diff options
-rw-r--r-- | ui.cpp | 98 | ||||
-rw-r--r-- | ui.hpp | 29 |
2 files changed, 113 insertions, 14 deletions
@@ -706,6 +706,10 @@ void UI::Element::on_message(const Message& msg) { (void)msg; } +void UI::Element::on_add_child(Element* nch) { + (void)nch; +} + void UI::Element::on_render() { } @@ -734,6 +738,7 @@ void UI::Element::add_child(Element* ch) { } ch->parent = this; ui->layout_dirty = true; + on_add_child(ch); } void UI::Element::remove_child(Element* ch) { @@ -821,12 +826,7 @@ void UI::Toolbar::on_render() { } UI::Button::Button(UI* ui, Element* parent, const char* label): - Element(ui, parent) { - text = dup_stringh(ui->heap, label); -} - -UI::Button::~Button() { - heap_free(ui->heap, text); + Label(ui, parent, label) { } UI::Rect UI::Button::layout(const Rect& avail) { @@ -988,3 +988,89 @@ void UI::Modal::bring_to_front() { p->remove_child(this); p->add_child(this); } + +UI::Tree::Tree(UI* ui, Element* parent, const char* label): + Element(ui, parent), collapsed(0), expandbtn(0), text(0) { + text = ui->create_element<Label>(this, label); +} + +UI::Rect UI::Tree::layout(const Rect& avail) { + Rect cr(avail.x + ui_padding, avail.y, avail.w, avail.h); + Rect lr(0, avail.y, avail.w, avail.h); + Rect used(avail.x, avail.y, 0, 0); + Element* child; + Rect er = Rect(cr.x, cr.y, 0, 0); + if (expandbtn) + er = expandbtn->layout(cr); + lr.x = er.x + er.w + ui_padding; + Rect tr = text->layout(lr); + er.h += ui_padding; + used.h = er.h; + used.w = (tr.x + tr.w) - er.x; + cr.y += er.h; + cr.h -= er.h; + for (child = children; child; child = child->next) { + if (child == expandbtn || child == text) continue; + Rect r = child->layout(cr); + r.h += ui_padding; + cr.y += r.h; + cr.h -= r.h; + used.h += r.h; + } + used.h += ui_padding; + bound = used; + clip = used; + clip.clip(avail); + return bound; +} + +void UI::Tree::on_render() { + if (collapsed) { + expandbtn->render(); + text->render(); + } +} + +void UI::Tree::on_update() { + if (collapsed) { + expandbtn->update(); + text->update(); + } +} + +void UI::Tree::on_add_child(Element* child) { + assert(collapsed == 0); + if (!expandbtn && text) { + expandbtn = (Button*)0x1; + expandbtn = ui->create_element<Button>(this, "-"); + expandbtn->handler = [](Element* e, const Message& m) { + if (m.type == Message::Type::click) { + UI::Tree* t = (UI::Tree*)e->parent; + if (t->collapsed) + t->expand(); + else + t->collapse(); + } + return 0; + }; + } + (void)child; +} + +void UI::Tree::expand() { + children = collapsed; + collapsed = 0; + if (expandbtn) + expandbtn->set_text("-"); +} + +void UI::Tree::collapse() { + collapsed = children; + children = 0; + if (expandbtn) + expandbtn->set_text("+"); +} + +bool UI::Tree::is_leaf() const { + return children == 0 && collapsed == 0; +} @@ -177,6 +177,7 @@ struct UI { void update(); virtual void on_update(); virtual void on_render(); + virtual void on_add_child(Element* nch); virtual void on_message(const Message& msg); void add_child(Element* ch); @@ -204,14 +205,6 @@ struct UI { void on_render() override; }; - struct Button : Element { - char* text; - Button(UI* ui, Element* parent, const char* label); - ~Button(); - Rect layout(const Rect& avail) override; - void on_render() override; - }; - struct Label : Element { char* text; Label(UI* ui, Element* parent, const char* label); @@ -222,6 +215,12 @@ struct UI { void set_text(const char* s); }; + struct Button : Label { + Button(UI* ui, Element* parent, const char* label); + Rect layout(const Rect& avail) override; + void on_render() override; + }; + struct Modal : Element { Container* contents; Toolbar* title_bar; @@ -236,6 +235,20 @@ struct UI { void on_update() override; void bring_to_front(); }; + + struct Tree : Element { + Element* collapsed; /* <- children are moved here when it's collapsed so they stop layout'ing and rendering! */ + Button* expandbtn; + Label* text; + Tree(UI* ui, Element* parent, const char* text); + Rect layout(const Rect& avail) override; + void on_render() override; + void on_update() override; + void on_add_child(Element* child) override; + void expand(); + void collapse(); + bool is_leaf() const; + }; }; #endif |