#include "noesis_shim.h"
#include <NsCore/BaseComponent.h>
#include <NsCore/Boxing.h>
#include <NsCore/DynamicCast.h>
#include <NsCore/Factory.h>
#include <NsCore/Noesis.h>
#include <NsCore/Ptr.h>
#include <NsCore/Reflection.h>
#include <NsCore/Symbol.h>
#include <NsCore/TypeClass.h>
#include <NsCore/TypeConverter.h>
#include <NsCore/TypeEnum.h>
#include <NsCore/TypeMeta.h>
#include <NsGui/ContentPropertyMetaData.h>
#include <NsGui/DependsOnMetaData.h>
#include <NsGui/RoutedEvent.h>
#include <NsGui/UIElement.h>
#include <NsGui/UIElementData.h>
namespace {
void* handout(Noesis::BaseComponent* c) {
if (!c) return nullptr;
c->AddReference();
return c;
}
const Noesis::Type* find_type(const char* name) {
if (!name) return nullptr;
Noesis::Symbol sym(name, Noesis::Symbol::NullIfNotFound());
if (sym.IsNull()) return nullptr;
return Noesis::Reflection::GetType(sym);
}
class DmRuntimeTypeEnum final: public Noesis::TypeEnum {
public:
explicit DmRuntimeTypeEnum(Noesis::Symbol name): TypeEnum(name) {}
bool GetValueObject(Noesis::Symbol name, Noesis::Ptr<Noesis::BoxedValue>& value) const override {
uint64_t v = 0;
if (HasName(name, v)) {
value = Noesis::Boxing::Box<int32_t>(static_cast<int32_t>(static_cast<uint32_t>(v)));
return true;
}
return false;
}
};
}
extern "C" void* noesis_register_enum(
const char* name, const noesis_enum_value* values, uint32_t count) {
if (!name || name[0] == '\0') return nullptr;
if (count > 0 && !values) return nullptr;
Noesis::Symbol sym(name);
if (Noesis::Reflection::IsTypeRegistered(sym)) {
return nullptr;
}
auto* te = new DmRuntimeTypeEnum(sym);
for (uint32_t i = 0; i < count; ++i) {
if (!values[i].name) continue;
te->AddValue(Noesis::Symbol(values[i].name),
static_cast<uint64_t>(static_cast<uint32_t>(values[i].value)));
}
Noesis::Reflection::RegisterType(te);
return static_cast<Noesis::Type*>(te);
}
extern "C" bool noesis_enum_value_from_name(
const char* enum_type, const char* value_name, int32_t* out_value) {
if (!value_name || !out_value) return false;
const auto* te = Noesis::DynamicCast<const Noesis::TypeEnum*>(find_type(enum_type));
if (!te) return false;
Noesis::Symbol member(value_name, Noesis::Symbol::NullIfNotFound());
if (member.IsNull()) return false;
uint64_t v = 0;
if (!te->HasName(member, v)) return false;
*out_value = static_cast<int32_t>(static_cast<uint32_t>(v));
return true;
}
extern "C" bool noesis_enum_name_from_value(
const char* enum_type, int32_t value, const char** out_name) {
if (!out_name) return false;
const auto* te = Noesis::DynamicCast<const Noesis::TypeEnum*>(find_type(enum_type));
if (!te) return false;
Noesis::Symbol name;
if (!te->HasValue(static_cast<uint64_t>(static_cast<uint32_t>(value)), name)) return false;
*out_name = name.Str();
return true;
}
extern "C" bool noesis_type_converter_from_string(
const char* type_name, const char* str, void** out_boxed) {
if (!str || !out_boxed) return false;
const Noesis::Type* t = find_type(type_name);
if (!t) return false;
Noesis::TypeConverter* conv = Noesis::TypeConverter::Get(t);
if (!conv) return false;
Noesis::Ptr<Noesis::BaseComponent> result;
if (!conv->TryConvertFromString(str, result)) return false;
*out_boxed = handout(result.GetPtr());
return true;
}
extern "C" bool noesis_register_routed_event(
const char* type_name, const char* event_name, int32_t strategy) {
if (!event_name) return false;
const auto* tc = Noesis::DynamicCast<const Noesis::TypeClass*>(find_type(type_name));
if (!tc) return false;
auto* uiData = Noesis::FindMeta<Noesis::UIElementData>(tc);
if (!uiData) return false;
Noesis::Symbol evSym(event_name);
if (uiData->FindEvent(evSym) != nullptr) {
return false; }
Noesis::RoutingStrategy rs;
switch (strategy) {
case 0: rs = Noesis::RoutingStrategy_Tunnel; break;
case 2: rs = Noesis::RoutingStrategy_Direct; break;
case 1:
default: rs = Noesis::RoutingStrategy_Bubble; break;
}
const Noesis::RoutedEvent* slot = nullptr;
uiData->RegisterEvent(slot, event_name, rs);
return slot != nullptr;
}
extern "C" bool noesis_raise_routed_event(void* element, const char* event_name) {
if (!element || !event_name) return false;
auto* uie = Noesis::DynamicCast<Noesis::UIElement*>(
static_cast<Noesis::BaseComponent*>(element));
if (!uie) return false;
Noesis::Symbol evSym(event_name, Noesis::Symbol::NullIfNotFound());
if (evSym.IsNull()) return false;
const Noesis::RoutedEvent* ev = Noesis::FindRoutedEvent(uie->GetClassType(), evSym);
if (!ev) return false;
Noesis::RoutedEventArgs args(uie, ev);
uie->RaiseEvent(args);
return true;
}
extern "C" bool noesis_factory_is_registered(const char* name) {
if (!name) return false;
Noesis::Symbol sym(name, Noesis::Symbol::NullIfNotFound());
if (sym.IsNull()) return false;
return Noesis::Factory::IsComponentRegistered(sym);
}
extern "C" bool noesis_type_set_content_property(
const char* type_name, const char* prop_name) {
if (!prop_name) return false;
const auto* tc = Noesis::DynamicCast<const Noesis::TypeClass*>(find_type(type_name));
if (!tc) return false;
auto* meta = const_cast<Noesis::TypeClass*>(tc);
Noesis::Ptr<Noesis::ContentPropertyMetaData> cp =
Noesis::MakePtr<Noesis::ContentPropertyMetaData>(prop_name);
meta->AddMeta(cp.GetPtr());
return true;
}
extern "C" bool noesis_type_get_content_property(
const char* type_name, const char** out_name) {
if (!out_name) return false;
const auto* tc = Noesis::DynamicCast<const Noesis::TypeClass*>(find_type(type_name));
if (!tc) return false;
const auto* cp = Noesis::FindMeta<Noesis::ContentPropertyMetaData>(tc);
if (!cp) return false;
*out_name = cp->GetContentProperty().Str();
return true;
}
extern "C" bool noesis_type_add_depends_on(
const char* type_name, const char* prop_name) {
if (!prop_name) return false;
const auto* tc = Noesis::DynamicCast<const Noesis::TypeClass*>(find_type(type_name));
if (!tc) return false;
auto* meta = const_cast<Noesis::TypeClass*>(tc);
Noesis::Ptr<Noesis::DependsOnMetaData> dep =
Noesis::MakePtr<Noesis::DependsOnMetaData>(prop_name);
meta->AddMeta(dep.GetPtr());
return true;
}
extern "C" bool noesis_type_get_depends_on(
const char* type_name, const char** out_name) {
if (!out_name) return false;
const auto* tc = Noesis::DynamicCast<const Noesis::TypeClass*>(find_type(type_name));
if (!tc) return false;
const auto* dep = Noesis::FindMeta<Noesis::DependsOnMetaData>(tc);
if (!dep) return false;
*out_name = dep->GetDependsOnProperty().Str();
return true;
}