// Generated by gmmproc 2.82.0 -- DO NOT MODIFY! #ifndef _GTKMM_EXPRESSION_H #define _GTKMM_EXPRESSION_H #include #include /* Copyright (C) 2020 The gtkmm Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ #include namespace Gtk { /** Base class for Gtk::Expression. * * @see Gtk::Expression * * @newin{3,98} */ class GTKMM_API ExpressionBase { public: #ifndef DOXYGEN_SHOULD_SKIP_THIS using CppObjectType = ExpressionBase; using BaseObjectType = GtkExpression; #endif /* DOXYGEN_SHOULD_SKIP_THIS */ /** Increment the reference count for this object. * You should never need to do this manually - use the object via a RefPtr instead. */ void reference() const; /** Decrement the reference count for this object. * You should never need to do this manually - use the object via a RefPtr instead. */ void unreference() const; ///Provides access to the underlying C instance. GtkExpression* gobj(); ///Provides access to the underlying C instance. const GtkExpression* gobj() const; ///Provides access to the underlying C instance. The caller is responsible for unrefing it. Use when directly setting fields in structs. GtkExpression* gobj_copy() const; ExpressionBase() = delete; // noncopyable ExpressionBase(const ExpressionBase&) = delete; ExpressionBase& operator=(const ExpressionBase&) = delete; protected: // Do not derive this. Gtk::ExpressionBase can neither be constructed nor deleted. void operator delete(void*, std::size_t); private: public: /** For instance: void on_notify(); * * Callback called by Gtk::Expression::watch() when the expression * value changes. */ using SlotNotify = sigc::slot; /** Gets the `GType` that this expression evaluates to. * * This type is constant and will not change over the lifetime * of this expression. * * @return The type returned from Gtk::Expression::evaluate(). */ GType get_value_type() const; /** Checks if the expression is static. * * A static expression will never change its result when * Gtk::Expression::evaluate() is called on it with the same arguments. * * That means a call to Gtk::Expression::watch() is not necessary because * it will never trigger a notify. * * @return true if the expression is static. */ bool is_static() const; }; // ExpressionBase /** Expressions to values. * * %Gtk::Expression provides a way to describe references to values. * * An important aspect of expressions is that the value can be obtained * from a source that is several steps away. For example, an expression * may describe ‘the value of property A of @a object1, which is itself the * value of a property of @a object2’. And @a object1 may not even exist yet * at the time that the expression is created. This is contrast to * Glib::Binding, which can only create direct connections between * the properties of two objects that must both exist for the duration * of the binding. * * An expression needs to be "evaluated" to obtain the value that it currently * refers to. An evaluation always happens in the context of a current object * called `this` (it mirrors the behavior of object-oriented languages), * which may or may not influence the result of the evaluation. Use * evaluate() for evaluating an expression. * * Various methods for defining expressions exist, from simple constants via * Gtk::ConstantExpression() to looking up properties in an object (even * recursively) via Gtk::PropertyExpression() or providing custom functions * to transform and combine expressions via Gtk::ClosureExpression(). * * Here is an example of a complex expression: * ~~~ * color_expr = Gtk::PropertyExpression>::create( * Gtk::ListItem::get_type(), "item"); * expression = Gtk::PropertyExpression::create( * GTK_TYPE_COLOR, color_expr, "name"); * ~~~ * when evaluated with `this` being a Gtk::ListItem, it will obtain the * "item" property from the Gtk::ListItem, and then obtain the "name" property * from the resulting object (which is assumed to be of type GTK_TYPE_COLOR). * * A more concise way to describe this would be * ~~~ * this->item->name * ~~~ * * The most likely place where you will encounter expressions is in the context * of list models and list widgets using them. For example, Gtk::DropDown is * evaluating a %Gtk::Expression to obtain strings from the items in its model * that it can then use to match against the contents of its search entry. * Gtk::StringFilter is using a %Gtk::Expression for similar reasons. * * By default, expressions are not paying attention to changes and evaluation is * just a snapshot of the current state at a given time. To get informed about * changes, an expression needs to be "watched" via a Gtk::ExpressionWatch, which * will cause a callback to be called whenever the value of the expression may * have changed. watch() starts watching an expression, and * Gtk::ExpressionWatch::unwatch() stops. * * Watches can be created for automatically updating the propery of an object, * similar to the Glib::Binding mechanism, by using bind(). * * @newin{3,98} */ template class Expression : public ExpressionBase { public: using ValueType = T; /** Evaluates the given expression and on success returns the result. * * It is possible that expressions cannot be evaluated - for example * when the expression references objects that have been destroyed or * set to nullptr. In that case the returned std::optional * will not contain a value. * * @param this_ The this argument for the evaluation. * @return The optional result of the evaluation. */ std::optional evaluate(const Glib::RefPtr& this_); /** Installs a watch for the expression that calls the @a notify function * whenever the evaluation of the expression may have changed. * * GTK cannot guarantee that the evaluation did indeed change when the @a notify * gets invoked, but it guarantees the opposite: When it did in fact change, * the @a notify will be invoked. * * @param this_ The `this` argument to watch. * @param notify Callback to invoke when the expression changes. * @return The newly installed watch. */ Glib::RefPtr> watch(const Glib::RefPtr& this_, const SlotNotify& notify); /** Bind a target's @a property to the expression. * * The value that the expression evaluates to is set on the target. * This is repeated whenever the expression changes to ensure that * the object's property stays synchronized with the expression. * * If the expression's evaluation fails, target's @a property is not updated. * You can ensure that this doesn't happen by using a fallback * expression. * * @param property Property on the target to bind to. * @param this_ The this argument for the evaluation of the expression. * @return A Gtk::ExpressionWatch. */ template Glib::RefPtr> bind(const Glib::PropertyProxy& property, const Glib::RefPtr& this_ = nullptr); /** @copydoc bind(const Glib::PropertyProxy&,const Glib::RefPtr&) */ template Glib::RefPtr> bind(const Glib::PropertyProxy_WriteOnly& property, const Glib::RefPtr& this_ = nullptr); }; // Expression template class PropertyExpression final : public Expression { public: /** Get the GType for this class, for use with the underlying GObject type system. */ static GType get_type() G_GNUC_CONST; /** Creates an expression that looks up a property via the * `this` argument. * * If the resulting object conforms to @a this_type, its property * named @a property_name will be queried. * Otherwise, this expression's evaluation will fail. * * The given @a this_type must have a property with @a property_name. * * @param this_type The type to expect for the this type. * @param property_name Name of the property. * @return A new Gtk::Expression. */ static Glib::RefPtr create(GType this_type, const Glib::ustring& property_name); /** Creates an expression that looks up a property via the * given @a expression. * * If the resulting object conforms to @a OT, its property * named @a property_name will be queried. * Otherwise, this expression's evaluation will fail. * * The value type of the given @a expression must have a property with * @a property_name. * * @param expression Expression to evaluate to get the object to query. * @param property_name Name of the property. * @return A new Gtk::Expression. */ template static Glib::RefPtr create(const Glib::RefPtr& expression, const Glib::ustring& property_name); /** Creates an expression that looks up a property via the * given @a expression. * * If the resulting object conforms to @a this_type, its property * named @a property_name will be queried. * Otherwise, this expression's evaluation will fail. * * The given @a this_type must have a property with @a property_name. * * @param this_type The type to expect for the this type. * @param expression Expression to evaluate to get the object to query. * @param property_name Name of the property. * @return A new Gtk::Expression. */ template static Glib::RefPtr create(GType this_type, const Glib::RefPtr& expression, const Glib::ustring& property_name); }; // PropertyExpression template class ConstantExpression final : public Expression { public: /** Get the GType for this class, for use with the underlying GObject type system. */ static GType get_type() G_GNUC_CONST; /** Creates a Gtk::Expression that evaluates to the object given by * the arguments. * * @param args Arguments to create the object from. * @return A new Gtk::Expression. */ template static Glib::RefPtr> create(T_Args&&... args); /** Creates an expression that always evaluates to the given @a value. * * @param value A Value. * @return A new Gtk::Expression. */ static Glib::RefPtr> create_for_value(const Glib::Value& value); }; // ConstantExpression template class ObjectExpression final : public Expression { public: /** Get the GType for this class, for use with the underlying GObject type system. */ static GType get_type() G_GNUC_CONST; /** Creates an expression evaluating to the given @a object with a weak reference. * Once the @a object is disposed, it will fail to evaluate. * This expression is meant to break reference cycles. * * If you want to keep a reference to @a object, use Gtk::ConstantExpression::create(). * * @param object %Object to watch. * @return A new Gtk::Expression. */ static Glib::RefPtr> create(const T& object); }; // ObjectExpression template class ClosureExpression final : public Expression { public: /** Get the GType for this class, for use with the underlying GObject type system. */ static GType get_type() G_GNUC_CONST; /** Creates a Gtk::Expression that calls @a slot when it is evaluated. * @a slot is called with the @a this object and the results of evaluating * the @a params expressions. * * Example: * ~~~ * Glib::ustring get_string(Glib::RefPtr this_, double a, int b) * { * return Glib::ustring::sprintf("a is %f, b is %d", a, b); * } * * Glib::RefPtr> expr1 = ... * Glib::RefPtr> expr2 = ... * * Glib::RefPtr> expr3 = * Gtk::ClosureExpression::create( * sigc::ptr_fun(get_string), expr1, expr2); * ~~~ * * @param slot Slot to call when evaluating this expression. * @param params Expressions for each parameter. * @return A new Gtk::Expression. */ template static Glib::RefPtr> create(S slot, const Glib::RefPtr&... params); private: template static void fill_params(GtkExpression** gparams, const Glib::RefPtr& a1, const Glib::RefPtr&... eas); static void fill_params(GtkExpression** gparams); }; // ClosureExpression #ifndef DOXYGEN_SHOULD_SKIP_THIS namespace Expression_Private { //TODO: Remove watch_callback() when we can break ABI. GTKMM_API void watch_callback(gpointer data); extern "C" { GTKMM_API void gtkmm_Expression_watch_callback(gpointer data); GTKMM_API void gtkmm_Expression_watch_callback_destroy(gpointer data); } // extern "C" template class Invoker { public: explicit Invoker(const sigc::slot& slot); void invoke(const GValue* param_values, GValue* return_value); private: sigc::slot the_slot; template PT eval_param(const GValue* gv); template void invoke(const GValue* param_values, GValue* return_value, std::index_sequence); }; // Invoker template void closure_marshal(GClosure* closure, GValue* return_value, guint n_param_values, const GValue* param_values, gpointer invocation_hint, gpointer marshal_data); //TODO: Remove closure_callback_func() when we can break ABI. GTKMM_API void closure_callback_func(); template void closure_destroy(gpointer data, GClosure* closure); extern "C" { GTKMM_API void gtkmm_Expression_closure_marshal(GClosure* closure, GValue* return_value, guint n_param_values, const GValue* param_values, gpointer invocation_hint, gpointer marshal_data); GTKMM_API void gtkmm_Expression_closure_callback_func(); GTKMM_API void gtkmm_Expression_closure_destroy(gpointer data, GClosure* closure); } // extern "C" // Like GClosureMarshal and GClosureNotify, but with C++ linkage. using ExpressionClosureMarshalFuncType = void (*)(GClosure* closure, GValue* return_value, guint n_param_values, const GValue* param_values, gpointer invocation_hint, gpointer marshal_data); using ExpressionClosureDestroyFuncType = void (*)(gpointer data, GClosure* closure); struct ExpressionClosureData { ExpressionClosureMarshalFuncType func; ExpressionClosureDestroyFuncType destroy_func; void* data; // An Invoker<> }; } // namespace Expression_Private template std::optional Expression::evaluate(const Glib::RefPtr& this_) { Glib::Value value; bool result = gtk_expression_evaluate(gobj(), this_ ? this_->gobj() : nullptr, value.gobj()); if (!result) return {}; if (!G_VALUE_HOLDS(value.gobj(), Glib::Value::value_type())) { g_warning("%s: The evaluated expression has type '%s', expected '%s'", G_STRLOC, g_type_name(G_VALUE_TYPE(value.gobj())), g_type_name(Glib::Value::value_type())); return {}; } return value.get(); } template Glib::RefPtr> Expression::watch(const Glib::RefPtr& this_, const SlotNotify& notify) { auto slot_copy = new SlotNotify(notify); return Glib::wrap(gtk_expression_watch(gobj(), this_ ? this_->gobj() : nullptr, &Expression_Private::gtkmm_Expression_watch_callback, slot_copy, &Expression_Private::gtkmm_Expression_watch_callback_destroy), true); } template template Glib::RefPtr> Expression::bind(const Glib::PropertyProxy& property, const Glib::RefPtr& this_) { return Glib::wrap(gtk_expression_bind(gobj_copy(), property.get_object()->gobj(), property.get_name(), this_ ? this_->gobj() : nullptr), true); } template template Glib::RefPtr> Expression::bind( const Glib::PropertyProxy_WriteOnly& property, const Glib::RefPtr& this_) { return Glib::wrap(gtk_expression_bind(gobj_copy(), property.get_object()->gobj(), property.get_name(), this_ ? this_->gobj() : nullptr), true); } template GType PropertyExpression::get_type() { return gtk_property_expression_get_type(); } template Glib::RefPtr> PropertyExpression::create( GType this_type, const Glib::ustring& property_name) { return Glib::make_refptr_for_instance>( reinterpret_cast*>( gtk_property_expression_new(this_type, nullptr, property_name.c_str()))); } template template Glib::RefPtr> PropertyExpression::create( const Glib::RefPtr& expression, const Glib::ustring& property_name) { return Glib::make_refptr_for_instance>( reinterpret_cast*>( gtk_property_expression_new(Glib::Value::value_type(), expression->gobj_copy(), property_name.c_str()))); } template template Glib::RefPtr> PropertyExpression::create( GType this_type, const Glib::RefPtr& expression, const Glib::ustring& property_name) { return Glib::make_refptr_for_instance>( reinterpret_cast*>( gtk_property_expression_new(this_type, expression->gobj_copy(), property_name.c_str()))); } template GType ConstantExpression::get_type() { return gtk_constant_expression_get_type(); } template template Glib::RefPtr> ConstantExpression::create(T_Args&&... args) { Glib::Value value; value.init(Glib::Value::value_type()); value.set(T(std::forward(args)...)); return create_for_value(value); } template Glib::RefPtr> ConstantExpression::create_for_value( const Glib::Value& value) { return Glib::make_refptr_for_instance>( reinterpret_cast*>( gtk_constant_expression_new_for_value(value.gobj()))); } template GType ObjectExpression::get_type() { return gtk_object_expression_get_type(); } template Glib::RefPtr> ObjectExpression::create(const T& object) { return Glib::make_refptr_for_instance>( reinterpret_cast*>( gtk_object_expression_new(G_OBJECT(object->gobj())))); } template GType ClosureExpression::get_type() { return gtk_cclosure_expression_get_type(); } template template Glib::RefPtr> ClosureExpression::create(S slot, const Glib::RefPtr&... params) { using TI = Expression_Private::Invoker, typename ATs::ValueType...>; auto invoker = new TI(slot); guint n_params = sizeof...(params); auto gparams = new GtkExpression*[n_params]; fill_params(gparams, params...); auto marshal_data = new Expression_Private::ExpressionClosureData{ &Expression_Private::closure_marshal, &Expression_Private::closure_destroy, invoker}; auto object = gtk_cclosure_expression_new( Glib::Value::value_type(), &Expression_Private::gtkmm_Expression_closure_marshal, n_params, gparams, &Expression_Private::gtkmm_Expression_closure_callback_func, marshal_data, &Expression_Private::gtkmm_Expression_closure_destroy); delete[] gparams; return Glib::make_refptr_for_instance>( reinterpret_cast*>(object)); } template template void ClosureExpression::fill_params(GtkExpression** gparams, const Glib::RefPtr& a1, const Glib::RefPtr&... eas) { gparams[0] = a1->gobj_copy(); fill_params(gparams + 1, eas...); } template void ClosureExpression::fill_params(GtkExpression**) {} namespace Expression_Private { template Invoker::Invoker(const sigc::slot& slot) : the_slot(slot) {} template template PT Invoker::eval_param(const GValue* gv) { Glib::Value v; v.init(gv); return v.get(); } template template void Invoker::invoke(const GValue* param_values, GValue* return_value, std::index_sequence) { T res = the_slot(eval_param(¶m_values[I])...); Glib::Value rv; rv.init(Glib::Value::value_type()); rv.set(res); g_value_copy(rv.gobj(), return_value); } template void Invoker::invoke(const GValue* param_values, GValue* return_value) { invoke(param_values, return_value, std::make_index_sequence()); } template void closure_marshal(GClosure* closure, GValue* return_value, guint, const GValue* param_values, gpointer, gpointer) { static_cast(closure->data)->invoke(param_values, return_value); } template void closure_destroy(gpointer, GClosure* closure) { delete static_cast(closure->data); } } // namespace Expression_Private #endif //DOXYGEN_SHOULD_SKIP_THIS } // namespace Gtk namespace Glib { template RefPtr> wrap(GtkExpression* object, bool take_copy = false) { if (take_copy && object) gtk_expression_ref(object); return Glib::make_refptr_for_instance>( reinterpret_cast*>(object)); } template class Value>> : public ValueBase { public: using CppType = RefPtr>; static GType value_type(); void set(const CppType& data); CppType get() const; }; template GType Value>>::value_type() { return gtk_expression_get_type(); } template void Value>>::set(const CppType& data) { gtk_value_set_expression(&gobject_, const_cast(data->gobj())); } template typename Value>>::CppType Value>>::get() const { return wrap(gtk_value_get_expression(&gobject_), true); } } // namespace Glib namespace Glib { /** A Glib::wrap() method for this object. * * @param object The C instance. * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref. * @result A C++ instance that wraps this C instance. * * @relates Gtk::ExpressionBase */ GTKMM_API Glib::RefPtr wrap(GtkExpression* object, bool take_copy = false); } // namespace Glib #endif /* _GTKMM_EXPRESSION_H */