24#include <boost/format.hpp>
39 template <
typename Base = i_ui_element>
45 using i_ui_element::no_parent;
46 using i_ui_element::wrong_type;
50 using i_ui_element::data_t;
51 using i_ui_element::array_data_t;
57 iParser{ aParser }, iParent{ nullptr }, iName{ aParser.current_element() }, iFragmentName{ aParser.current_fragment() }, iTypeName{ aParser.current_element() }, iMemberElement{ false }, iId{ aParser.get_optional<
neolib::
string>(
"id") }, iAnonymousIdCounter{ 0u }, iType{ aType }
62 iParser{ aParser }, iParent{ nullptr }, iName{ aParser.current_element() }, iFragmentName{ aParser.current_fragment() }, iTypeName{ aParser.current_element() }, iMemberElement{ false }, iId{ aId }, iAnonymousIdCounter{ 0u }, iType{ aType }
67 iParser{ aParser }, iParent{ &aParent }, iName{ aParser.current_element() }, iFragmentName{ aParser.current_fragment() }, iTypeName{ aParser.current_element() }, iMemberElement{ false }, iAnonymousIdCounter{ 0u }, iId{ aParser.get_optional<
neolib::
string>(
"id") }, iType{ aType }
73 iParser{ aParser }, iParent{ &aParent }, iName{ aParser.current_element() }, iFragmentName{ aParser.current_fragment() }, iTypeName{ aParser.current_element() }, iMemberElement{ false }, iAnonymousIdCounter{ 0u }, iId{ aId }, iType{ aType }
79 iParser{ aParser }, iParent{ &aParent }, iName{ aParser.current_element() }, iFragmentName{ aParser.current_fragment() }, iTypeName{ aParser.current_element() }, iMemberElement{ true }, iAnonymousIdCounter{ 0u }, iId{}, iType{ aType }
103 if (iDragDrop != std::nullopt && *iDragDrop)
106 result =
"drag_drop_target<"_s + iTypeName +
">"_s;
113 iTypeName = aTypeName;
126 return iMemberElement;
145 iAnonymousId =
parent().generate_anonymous_id();
151 switch (
type() & ui_element_type::MASK_RESERVED_SPECIFIC)
153 case ui_element_type::Label:
154 iAnonymousId =
parent().id() +
".label()";
156 case ui_element_type::LineEdit:
157 iAnonymousId =
parent().id() +
".input_box()";
159 case ui_element_type::TextWidget:
160 iAnonymousId =
parent().id() +
".text_widget()";
162 case ui_element_type::ImageWidget:
163 iAnonymousId =
parent().id() +
".image_widget()";
166 throw unsupported_member_element();
170 return *iAnonymousId;
172 using base_type::generate_anonymous_id;
175 aNewAnonymousId =
neolib::string{
id() +
"_" + boost::lexical_cast<std::string>(++iAnonymousIdCounter) };
181 using base_type::check_element_ref;
185 auto e =
static_cast<const i_ui_element*
>(
this);
186 while (e->has_parent())
192 return const_cast<i_ui_element&
>(to_const(*this).fragment());
196 return iParent !=
nullptr;
198 const i_ui_element&
parent()
const override
206 return const_cast<i_ui_element&
>(to_const(*this).parent());
227 using i_ui_element::enum_to_string;
228 using i_ui_element::get_enum;
229 using i_ui_element::get_scalar;
230 using i_ui_element::get_scalars;
231 using i_ui_element::emplace_2;
232 using i_ui_element::emplace_4;
233 using i_ui_element::get_color;
241 iDataNames.merge(aNames);
247 std::cerr <<
parser().
source_location() <<
": warning: nrc: Unknown element key '" << aName <<
"' in element '" <<
id() <<
"'." << std::endl;
250 if (aName ==
"drag_drop")
252 iDragDrop = aData.get<
bool>();
257 iWidgetType = get_enum<widget_type>(aData);
258 if (aName ==
"weight")
259 iWeight.emplace(get_scalar<double>(aData));
260 else if (aName ==
"size_policy")
261 iSizePolicy = get_enum<size_constraint>(aData);
262 else if (aName ==
"alignment")
263 iAlignment = get_enum<alignment>(aData);
264 else if (aName ==
"size")
265 iFixedSize.emplace(get_scalar<length>(aData));
266 else if (aName ==
"minimum_size")
267 iMinimumSize.emplace(get_scalar<length>(aData));
268 else if (aName ==
"minimum_width")
269 iMinimumWidth.emplace(get_scalar<length>(aData));
270 else if (aName ==
"minimum_height")
271 iMinimumHeight.emplace(get_scalar<length>(aData));
272 else if (aName ==
"maximum_size")
273 iMaximumSize.emplace(get_scalar<length>(aData));
274 else if (aName ==
"maximum_width")
275 iMaximumWidth.emplace(get_scalar<length>(aData));
276 else if (aName ==
"maximum_height")
277 iMaximumHeight.emplace(get_scalar<length>(aData));
278 else if (aName ==
"padding")
279 iPadding.emplace(get_scalar<length>(aData));
280 else if (aName ==
"enabled")
281 iEnabled = aData.get<
bool>();
282 else if (aName ==
"disabled")
283 iEnabled = !aData.get<
bool>();
284 else if (aName ==
"focus_policy")
285 iFocusPolicy.first = get_enum<focus_policy>(aData);
286 else if (aName ==
"text")
288 else if (aName ==
"label")
290 else if (aName ==
"image" || (aName ==
"uri" && (
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::ImageWidget))
292 else if (aName ==
"aspect_ratio")
293 iAspectRatio = get_enum<aspect_ratio>(aData);
294 else if (aName ==
"placement")
296 if ((
type() & ui_element_type::MASK_RESERVED_SPECIFIC) != ui_element_type::TextField)
298 if ((
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::Label || (
type() & ui_element_type::HasLabel) == ui_element_type::HasLabel)
299 iLabelPlacement = get_enum<label_placement>(aData);
300 else if ((
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::ImageWidget || (
type() & ui_element_type::HasImage) == ui_element_type::HasImage)
301 iImagePlacement = get_enum<cardinal>(aData);
304 iTextFieldPlacement = get_enum<text_field_placement>(aData);
306 else if (aName ==
"base_color")
307 iBaseColor = get_color(aData);
308 else if (aName ==
"background_color")
309 iBackgroundColor = get_color(aData);
310 else if (aName ==
"opacity")
311 iOpacity = aData.get<
double>();
312 else if (aName ==
"transparency")
313 iOpacity = 1.0 - aData.get<
double>();
314 else if (aName ==
"default_focus")
321 std::cerr <<
parser().
source_location() <<
": warning: nrc: Unknown element key '" << aName <<
"' in element '" <<
id() <<
"'." << std::endl;
324 if (aName ==
"size_policy" && !aArrayData.
empty())
325 iSizePolicy = size_policy::from_string(
326 aArrayData[0u].get<neolib::i_string>().to_std_string(),
328 else if (aName ==
"alignment")
329 iAlignment = get_enum<alignment>(aArrayData);
330 else if (aName ==
"size")
331 emplace_2<length>(
"size", iFixedSize);
332 else if (aName ==
"minimum_size")
333 emplace_2<length>(
"minimum_size", iMinimumSize);
334 else if (aName ==
"maximum_size")
335 emplace_2<length>(
"maximum_size", iMaximumSize);
336 else if (aName ==
"padding")
337 emplace_4<length>(
"padding", iPadding);
338 else if (aName ==
"weight")
339 emplace_2<double>(
"weight", iWeight);
340 else if (aName ==
"focus_policy")
341 iFocusPolicy.first = get_enum<focus_policy>(aArrayData, iFocusPolicy.second,
"Default");
342 else if (aName ==
"base_color")
343 iBaseColor = get_color(aArrayData);
344 else if (aName ==
"background_color")
345 iBackgroundColor = get_color(aArrayData);
350 auto part = fullRef.find_first_of(
'.');
351 auto ref = fullRef.substr(0, part);
353 if (!resolved || (part == std::string::npos && resolved->fragment_name() !=
fragment_name()))
354 throw element_not_found(std::string{ ref });
355 if (part != std::string::npos)
366 temp +=
"i_widget& aParent";
367 for (
auto const& ref : iRefs)
372 temp += e.fragment_name().to_std_string() +
"& " + e.id().to_std_string();
374 if (aParamsAfter && !temp.empty())
390 temp =
" " + temp +
" ";
398 for (
auto const& child :
children())
399 child->emit_preamble();
403 for (
auto const& child :
children())
409 emit(
" %1%.set_size_policy(%2%);\n",
id(), *iSizePolicy);
411 emit(
" %1%.set_alignment(%2%);\n",
id(), enum_to_string(
"alignment", *iAlignment));
413 emit(
" %1%.set_fixed_size(size{ %2%, %3% });\n",
id(), iFixedSize->cx, iFixedSize->cy);
415 emit(
" %1%.set_minimum_size(size{ %2%, %3% });\n",
id(), iMinimumSize->cx, iMinimumSize->cy);
417 emit(
" %1%.set_minimum_width(%2%);\n",
id(), *iMinimumWidth);
419 emit(
" %1%.set_minimum_height(%2%);\n",
id(), *iMinimumHeight);
421 emit(
" %1%.set_maximum_size(size{ %2%, %3% });\n",
id(), iMaximumSize->cx, iMaximumSize->cy);
423 emit(
" %1%.set_maximum_width(%2%);\n",
id(), *iMaximumWidth);
425 emit(
" %1%.set_maximum_height(%2%);\n",
id(), *iMaximumHeight);
427 emit(
" %1%.set_weight(size{ %2%, %3% });\n",
id(), iWeight->cx, iWeight->cy);
430 auto const&
padding = *iPadding;
434 emit(
" %1%.set_padding(neogfx::padding{ %2% });\n",
id(),
padding.
left);
442 emit(
" %1%.%2%();\n",
id(), *iEnabled ?
"enable" :
"disable");
443 if (iFocusPolicy.first)
445 if (!iFocusPolicy.second)
446 emit(
" %1%.set_focus_policy(%2%);\n",
id(), enum_to_string(
"focus_policy", *iFocusPolicy.first));
448 emit(
" %1%.set_focus_policy(%1%.focus_policy() | %2%);\n",
id(), enum_to_string(
"focus_policy", *iFocusPolicy.first));
451 emit(
" %1%.set_placement(%2%);\n",
id(), enum_to_string(
"label_placement", *iLabelPlacement));
452 if (iTextFieldPlacement)
453 emit(
" %1%.set_placement(%2%);\n",
id(), enum_to_string(
"text_field_placement", *iTextFieldPlacement));
455 emit(
" %1%.set_image(image{ \"%2%\" });\n",
id(), *iImage);
457 emit(
" %1%.set_aspect_ratio(%2%);\n",
id(), enum_to_string(
"aspect_ratio", *iAspectRatio));
459 emit(
" %1%.set_placement(%2%);\n",
id(), enum_to_string(
"cardinal", *iImagePlacement));
461 emit(
" %1%.set_text(\"%2%\"_t);\n",
id(), *iText);
463 emit(
" %1%.label().set_text(\"%2%\"_t);\n",
id(), *iLabelText);
465 emit(
" %1%.set_opacity(%2%);\n",
id(), *iOpacity);
467 emit(
" %1%.set_base_color(color{ %2% });\n",
id(), *iBaseColor);
468 if (iBackgroundColor)
469 emit(
" %1%.set_background_color(color{ %2% });\n",
id(), *iBackgroundColor);
472 check_element_ref(*iDefaultFocus);
473 emit(
" %1%.set_focus();\n", *iDefaultFocus);
475 if ((
type() & ui_element_type::Widget) == ui_element_type::Widget &&
476 (
type() & ui_element_type::Separator) != ui_element_type::Separator &&
has_parent() &&
477 (
parent().
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::StatusBar)
480 emit(
" %1%.set_padding(neogfx::padding{});\n",
id());
481 emit(
" %1%.set_font_role(font_role::StatusBar);\n",
id());
483 for (
auto const& child :
children())
489 if ((
parent().
type() & ui_element_type::MASK_RESERVED_GENERIC) == ui_element_type::Window)
491 switch (
type() & ui_element_type::MASK_RESERVED_SPECIFIC)
493 case ui_element_type::MenuBar:
494 return ".menu_layout()";
495 case ui_element_type::Toolbar:
496 return ".toolbar_layout()";
497 case ui_element_type::StatusBar:
500 return ".client_layout()";
503 else if ((
parent().
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::GroupBox)
504 return ".item_layout()";
505 else if ((
parent().
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::StatusBar)
506 return ".normal_layout()";
522 " %1%{ %2%%3%, \"%4%\"_t }",
id(),
parent().
id(),
layout(), *aText);
524 template <
typename Enum>
530 " %1%{ %2%%3%, %4% }",
id(),
parent().
id(),
layout(), enum_to_string(aEnumName, aEnum));
532 template <
typename T>
538 " %1%{ %2%%3%, %4% }",
id(),
parent().
id(),
layout(), aArgument);
541 void emit(std::string
const& aArgument)
const
545 template <
typename... Args>
546 void emit(std::string
const& aFormat,
const Args&... aArguments)
const
548 parser().
emit(aFormat, base_type::convert_emit_argument(aArguments)...);
556 if (!
has_parent() && (
type() & ui_element_type::Widget) == ui_element_type::Widget)
558 if ((
type() & ui_element_type::Widget) == ui_element_type::Widget)
559 add_data_names({
"drag_drop",
"enabled",
"disabled",
"focus_policy" });
560 if ((
type() & ui_element_type::HasGeometry) == ui_element_type::HasGeometry)
561 add_data_names({
"size_policy",
"padding",
"minimum_size",
"maximum_size",
"size",
"minimum_width",
"minimum_height",
"maximum_width",
"maximum_height",
"weight" });
562 if ((
type() & ui_element_type::HasAlignment) == ui_element_type::HasAlignment)
564 if ((
type() & (ui_element_type::HasText | ui_element_type::HasLabel)) != ui_element_type::None)
566 if ((
type() & (ui_element_type::HasImage | ui_element_type::HasLabel)) != ui_element_type::None)
568 if ((
type() & ui_element_type::MASK_RESERVED_SPECIFIC) == ui_element_type::ImageWidget)
570 if ((
type() & ui_element_type::HasColor) == ui_element_type::HasColor)
571 add_data_names({
"base_color",
"background_color",
"opacity",
"transparency" });
574 const i_ui_element_parser& iParser;
575 i_ui_element* iParent;
584 mutable uint32_t iAnonymousIdCounter;
588 std::optional<bool> iDragDrop;
589 std::optional<widget_type> iWidgetType;
590 std::optional<size_policy> iSizePolicy;
591 std::optional<alignment> iAlignment;
592 std::optional<basic_size<length>> iFixedSize;
593 std::optional<basic_size<length>> iMinimumSize;
594 std::optional<basic_size<length>> iMaximumSize;
595 std::optional<length> iMinimumWidth;
596 std::optional<length> iMinimumHeight;
597 std::optional<length> iMaximumWidth;
598 std::optional<length> iMaximumHeight;
599 std::optional<size> iWeight;
600 std::optional<basic_padding<length>> iPadding;
601 std::optional<bool> iEnabled;
602 std::pair<std::optional<focus_policy>,
bool> iFocusPolicy;
603 std::optional<label_placement> iLabelPlacement;
604 std::optional<text_field_placement> iTextFieldPlacement;
605 std::optional<string> iText;
606 std::optional<string> iLabelText;
607 std::optional<string> iImage;
608 std::optional<aspect_ratio> iAspectRatio;
609 std::optional<cardinal> iImagePlacement;
610 std::optional<double> iOpacity;
611 std::optional<color> iBaseColor;
612 std::optional<color> iBackgroundColor;
613 std::optional<string> iDefaultFocus;
virtual void index(const neolib::i_string &aId, const i_ui_element &aElement) const =0
virtual void emit(const neolib::i_string &aText) const =0
std::string source_location() const
virtual const i_ui_element * find(const neolib::i_string &aId) const =0
virtual void generate_anonymous_id(neolib::i_string &aNewAnonymousId) const =0
virtual const i_ui_element & at(const neolib::i_string &aId) const =0
void emit_ctor() const override
bool is_member_element() const override
neolib::ref_ptr< i_ui_element > element_ptr_t
const neolib::i_string & generate_base_ctor_args(bool aArgsAfter=false) const override
void emit_generic_ctor() const
const children_t & children() const override
i_ui_element & fragment() override
void set_type_name(const neolib::i_string &aTypeName) override
void parse(const neolib::i_string &aName, const data_t &aData) override
i_ui_element & parent() override
ui_element(const i_ui_element_parser &aParser, i_ui_element &aParent, member_element_t, ui_element_type aType)
const i_ui_element & parent() const override
const neolib::i_string & generate_ctor_params(bool aParamsAfter=false) const override
ui_element_type type() const override
void generate_anonymous_id(neolib::i_string &aNewAnonymousId) const override
void add_header(std::string const &aHeader)
const neolib::i_string & anonymous_id() const override
const neolib::i_string & name() const override
neolib::vector< neolib::simple_variant > concrete_array_data_t
neolib::string layout() const
bool anonymous() const override
const neolib::i_string & type_name() const override
const neolib::i_string & fragment_name() const override
void emit(std::string const &aArgument) const
void emit_preamble() const override
void emit(std::string const &aFormat, const Args &... aArguments) const
void emit_body() const override
ui_element(const i_ui_element_parser &aParser, ui_element_type aType)
const i_ui_element & fragment() const override
const data_names_t & data_names() const
void parse(const neolib::i_string &aName, const array_data_t &aArrayData) override
void add_data_names(data_names_t aNames)
void emit_generic_ctor(const T &aArgument) const
neolib::vector< element_ptr_t > children_t
void instantiate(i_app &aApp) override
ui_element(const i_ui_element_parser &aParser, i_ui_element &aParent, ui_element_type aType, const neolib::optional< neolib::string > &aId)
const i_ui_element_parser & parser() const override
const neolib::i_set< neolib::i_string > & element_refs() const override
void instantiate(i_layout &aLayout) override
children_t & children() override
const neolib::i_string & id() const override
void instantiate(i_widget &aWidget) override
ui_element(const i_ui_element_parser &aParser, ui_element_type aType, const neolib::optional< neolib::string > &aId)
std::enable_if_t< std::is_enum_v< Enum >, void > emit_generic_ctor(std::string const &aEnumName, Enum aEnum) const
void add_element_ref(const neolib::i_string &aRef) override
std::set< std::string > data_names_t
ui_element(const i_ui_element_parser &aParser, i_ui_element &aParent, ui_element_type aType)
bool has_parent() const override
const neolib::i_vector< neolib::i_string > & headers() const override
void emit_generic_ctor(const std::optional< neolib::string > &aText) const
bool empty() const noexcept
std::string_view to_std_string_view() const noexcept
std::string to_std_string() const
void push_back(abstract_value_type const &aValue) final
object_type ui_element_type