Rework container properties to be more elegant. More UI stuff.

This commit is contained in:
David Given
2021-12-09 23:00:37 +01:00
parent 5ff7651218
commit eb0bb2cc2f
2 changed files with 166 additions and 42 deletions

View File

@@ -34,14 +34,34 @@ public:
->setChild( ->setChild(
make<UIVBox>() make<UIVBox>()
->add(make<UIHBox>() ->add(make<UIHBox>()
->add(make<UICombo<ConfigProto*>>()->setOptions(configs)) ->add(make<UISelect<ConfigProto*>>()
->add(_busyButton = make<UIButton>("busy button")) ->setOptions(configs)
->add(make<UIButton>("press me!")) ->setBoxParams({ .expand = true }))
->add(make<UICombo>()
->setOptions({
"drive:0",
"drive:1",
})
->setBoxParams({ .expand = true }))
)
->add(make<UIGrid>()
->add(make<UIButton>("Load image")->setGridParams({ .x = 0 }))
->add(make<UIButton>("Write disk")->setGridParams({ .x = 1 }))
->add(make<UIHBox>()
->add(make<UILabel>("Cylinders:"))
->add(make<UITextEntry>())
->add(make<UILabel>("Heads:"))
->add(make<UITextEntry>())
->add(make<UICheckBox>("HD"))
->setGridParams({ .x = 2, .hexpand = true, .vexpand = true }))
->add(make<UIButton>("Read disk")->setGridParams({ .x = 3 }))
->add(make<UIButton>("Save image")->setGridParams({ .x = 4 }))
) )
->add(make<UIArea>() ->add(make<UIArea>()
->setOnDraw(_onredraw_cb) ->setOnDraw(_onredraw_cb)
->setStretchy(true) ->disable()
->disable()) ->setBoxParams({ .expand = true }))
->add(_busyButton = make<UIButton>("busy button"))
->add(make<UIButton>("press me again!")) ->add(make<UIButton>("press me again!"))
); );

View File

@@ -1,6 +1,23 @@
#ifndef UIPP_H #ifndef UIPP_H
#define UIPP_H #define UIPP_H
struct UIGridParams
{
int x = 0;
int y = 0;
int xspan = 1;
int yspan = 1;
bool hexpand = false;
uiAlign halign = uiAlignFill;
bool vexpand = false;
uiAlign valign = uiAlignFill;
};
struct UIBoxParams
{
bool expand = false;
};
class Closeable class Closeable
{ {
public: public:
@@ -47,29 +64,46 @@ public:
return _control; return _control;
} }
bool stretchy() const
{
return _stretchy;
}
bool built() const bool built() const
{ {
return !!_control; return !!_control;
} }
public: public:
UIControl* setStretchy(bool stretchy) { _stretchy = stretchy; return this; }
UIControl* show() { uiControlShow(claim()); return this; } UIControl* show() { uiControlShow(claim()); return this; }
UIControl* hide() { uiControlHide(control()); return this; } UIControl* hide() { uiControlHide(control()); return this; }
UIControl* enable() { uiControlEnable(control()); return this; } UIControl* enable() { uiControlEnable(control()); return this; }
UIControl* disable() { uiControlDisable(control()); return this; } UIControl* disable() { uiControlDisable(control()); return this; }
public:
UIGridParams& getGridParams() {
if (!_gridParams)
_gridParams = UIGridParams();
return *_gridParams;
}
UIBoxParams& getBoxParams() {
if (!_boxParams)
_boxParams = UIBoxParams();
return *_boxParams;
}
UIControl* setGridParams(UIGridParams params) {
_gridParams = params;
return this;
}
UIControl* setBoxParams(UIBoxParams params) {
_boxParams = params;
return this;
}
private: private:
uiControl* _control; uiControl* _control;
bool _owned = true; bool _owned = true;
bool _stretchy = false;
bool _enabled = true; bool _enabled = true;
std::optional<UIGridParams> _gridParams;
std::optional<UIBoxParams> _boxParams;
}; };
template <class T, class B> template <class T, class B>
@@ -86,34 +120,20 @@ public:
} }
}; };
template <class T, class B> template <class B>
class UIContainerControl : public UITypedControl<T, B> class UIBox : public UITypedControl<uiBox, B>
{ {
public: public:
UIContainerControl(T* control): UIBox(uiBox* control):
UITypedControl<T, B>(control) UITypedControl<uiBox, B>(control)
{} {}
B* add(UIControl* child) B* add(UIControl* child)
{ {
uiBoxAppend(this->typedControl(), child->claim(), child->stretchy()); const auto& params = child->getBoxParams();
_children.push_back(child); uiBoxAppend(this->typedControl(), child->claim(), params.expand);
return (B*) this; return (B*) this;
} }
const std::vector<UIControl*>& children() const { return _children; }
private:
std::vector<UIControl*> _children;
};
template <class B>
class UIBox : public UIContainerControl<uiBox, B>
{
public:
UIBox(uiBox* control):
UIContainerControl<uiBox, B>(control)
{}
}; };
class UIHBox : public UIBox<UIHBox> class UIHBox : public UIBox<UIHBox>
@@ -132,6 +152,49 @@ public:
{} {}
}; };
class UIGrid : public UITypedControl<uiGrid, UIGrid>
{
public:
UIGrid():
UITypedControl<uiGrid, UIGrid>(uiNewGrid())
{}
UIGrid* add(UIControl* child)
{
const auto& params = child->getGridParams();
uiGridAppend(this->typedControl(), child->claim(),
params.x, params.y,
params.xspan, params.yspan,
params.hexpand, params.halign,
params.vexpand, params.valign);
return this;
}
};
class UILabel : public UITypedControl<uiLabel, UILabel>
{
public:
UILabel(const std::string& text):
UITypedControl(uiNewLabel(text.c_str()))
{}
};
class UITextEntry : public UITypedControl<uiEntry, UITextEntry>
{
public:
UITextEntry():
UITypedControl(uiNewEntry())
{}
};
class UICheckBox : public UITypedControl<uiCheckbox, UICheckBox>
{
public:
UICheckBox(const std::string& text):
UITypedControl(uiNewCheckbox(text.c_str()))
{}
};
class UIArea : public UITypedControl<uiArea, UIArea> class UIArea : public UITypedControl<uiArea, UIArea>
{ {
public: public:
@@ -290,16 +353,16 @@ private:
}; };
template <typename T> template <typename T>
class UICombo : public UITypedControl<uiCombobox, UICombo<T>> class UISelect : public UITypedControl<uiCombobox, UISelect<T>>
{ {
public: public:
UICombo(): UISelect():
UITypedControl<uiCombobox, UICombo<T>>(uiNewCombobox()) UITypedControl<uiCombobox, UISelect<T>>(uiNewCombobox())
{ {
uiComboboxOnSelected(this->typedControl(), _selected_cb, this); uiComboboxOnSelected(this->typedControl(), _selected_cb, this);
} }
UICombo<T>* setOptions(const std::vector<std::pair<std::string, T>>& options) UISelect<T>* setOptions(const std::vector<std::pair<std::string, T>>& options)
{ {
assert(_forwards.empty()); assert(_forwards.empty());
int count = 0; int count = 0;
@@ -313,7 +376,7 @@ public:
return this; return this;
} }
UICombo<T>* select(T item) UISelect<T>* select(T item)
{ {
auto it = _backwards.find(item); auto it = _backwards.find(item);
if (it != _backwards.end()) if (it != _backwards.end())
@@ -333,12 +396,12 @@ public:
private: private:
static void _selected_cb(uiCombobox*, void* p) static void _selected_cb(uiCombobox*, void* p)
{ {
auto combo = ((UICombo<T>*)p); auto c = ((UISelect<T>*)p);
if (combo->_onselected) if (c->_onselected)
{ {
auto value = combo->getSelected(); auto value = c->getSelected();
if (value) if (value)
combo->_onselected(*value); c->_onselected(*value);
} }
} }
@@ -348,5 +411,46 @@ private:
std::function<void(T)> _onselected; std::function<void(T)> _onselected;
}; };
class UICombo : public UITypedControl<uiEditableCombobox, UICombo>
{
public:
UICombo():
UITypedControl<uiEditableCombobox, UICombo>(uiNewEditableCombobox())
{
uiEditableComboboxOnChanged(this->typedControl(), _changed_cb, this);
}
UICombo* setOptions(const std::vector<std::string>& options)
{
for (auto& p : options)
uiEditableComboboxAppend(this->typedControl(), p.c_str());
return this;
}
UICombo* setText(const std::string& text)
{
uiEditableComboboxSetText(this->typedControl(), text.c_str());
return this;
}
std::string getText()
{
return uiEditableComboboxText(this->typedControl());
}
private:
static void _changed_cb(uiEditableCombobox*, void* p)
{
auto c = ((UICombo*)p);
if (c->_onchanged)
{
auto value = c->getText();
c->_onchanged(value);
}
}
private:
std::function<void(const std::string&)> _onchanged;
};
#endif #endif