summaryrefslogtreecommitdiff
path: root/glib/glibmm/objectbase.h
blob: 2ad6e650301f133379c0ca3c2e2d21fe3c2c34c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// -*- c++ -*-
#ifndef _GLIBMM_OBJECTBASE_H
#define _GLIBMM_OBJECTBASE_H

/* $Id$ */

/* Copyright 2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <glibmm/signalproxy.h>
#include <glibmm/propertyproxy.h>
#include <glibmm/ustring.h>
#include <glibmm/value.h>
#include <sigc++/trackable.h>
#include <typeinfo>
#include <glibmmconfig.h>
#include <glibmm/debug.h>

#include <glibmmconfig.h>

GLIBMM_USING_STD(type_info)

#ifndef DOXYGEN_SHOULD_SKIP_THIS
extern "C" { typedef struct _GObject GObject; }
#endif


namespace Glib
{

#ifndef DOXYGEN_SHOULD_SKIP_THIS
class GSigConnectionNode;
#endif

//This inherits virtually from sigc::trackable so that people can multiply inherit glibmm classes from other sigc::trackable-derived classes.
//See bugzilla.gnome.org bug # 116280
/** Glib::ObjectBase is a common base class for Objects and Interfaces.
 *
 * This is used as virtual base class.  This means the ObjectBase
 * constructor runs before all others, either implicitly or explicitly.  Each of
 * the available constructors initializes custom_type_name_ in a different way.
 */
class GLIBMM_API ObjectBase : virtual public sigc::trackable
{
protected:
  /** This default constructor is called implicitly from the constructor of user-derived
   * classes, even if, for instance, Gtk::Button calls a different ObjectBase constructor.
   * This is normal behaviour for C++ virtual inheritance.
   * 
   * The GType name will be gtkmm__anonymous_custom_type.
   */
  ObjectBase();

  /** A derived constructor always overrides this choice.
   * The C++ language itself ensures that the constructor
   * is only invoked once.
   * 
   * All classes generated by gtkmmproc use this constructor, with custom_type_name = 0,
   * which essentially means it's not a custom type.  This is used to optimize
   * vfunc and signal handler callbacks -- since the C++ virtual methods are
   * not overridden, invocation can be skipped.
   *
   * The GType name will be @a custom_type_name.
   */
  explicit ObjectBase(const char* custom_type_name);

  /** This constructor is a special feature to allow creation of derived types on the
   * fly, without having to use g_object_new() manually.  This feature is
   * sometimes necessary, e.g. to implement a custom Gtk::CellRenderer.  The
   * neat trick with the virtual base class ctor makes it possible to reuse
   * the same direct base class' constructor as with non-custom types.
   *
   * The GType name will be @a custom_type_info.name().
   */
  explicit ObjectBase(const std::type_info& custom_type_info);

  virtual ~ObjectBase() = 0;

  // Called by Glib::Object and Glib::Interface constructors. See comments there.
  void initialize(GObject* castitem);

public:

  /// You probably want to use a specific property_*() accessor method instead.
  void set_property_value(const Glib::ustring& property_name, const Glib::ValueBase& value);

  /// You probably want to use a specific property_*() accessor method instead.
  void get_property_value(const Glib::ustring& property_name, Glib::ValueBase& value) const;

  /// You probably want to use a specific property_*() accessor method instead.
  template <class PropertyType>
  void set_property(const Glib::ustring& property_name, const PropertyType& value);

  /// You probably want to use a specific property_*() accessor method instead.
  template <class PropertyType>
  void get_property(const Glib::ustring& property_name, PropertyType& value) const;

  /** You can use the signal_changed() signal of the property proxy instead, 
   * but this is necessary when using the reduced API.
   */
  void connect_property_changed(const Glib::ustring& property_name, const sigc::slot<void>& slot);

  /** Increment the reference count for this object.
   * You should never need to do this manually - use the object via a RefPtr instead.
   */
  virtual 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.
   */
  virtual void unreference() const;

  ///Provides access to the underlying C GtkObject.
  inline GObject*       gobj()       { return gobject_; }

  ///Provides access to the underlying C GtkObject.
  inline const GObject* gobj() const { return gobject_; }

  /// Give a ref-ed copy to someone. Use for direct struct access.
  GObject* gobj_copy() const;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  static ObjectBase* _get_current_wrapper(GObject* object);
  bool _cpp_destruction_is_in_progress() const;
#endif //DOXYGEN_SHOULD_SKIP_THIS

protected:

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  GObject*            gobject_; // the GLib/GDK/GTK+ object instance
  const char*         custom_type_name_;
  bool                cpp_destruction_in_progress_;

  bool is_anonymous_custom_() const;
  bool is_derived_() const;

  static  void destroy_notify_callback_(void* data);
  virtual void destroy_notify_();

  void _set_current_wrapper(GObject* object);
#endif //DOXYGEN_SHOULD_SKIP_THIS

private:
  // noncopyable
  ObjectBase(const ObjectBase&);
  ObjectBase& operator=(const ObjectBase&);

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  virtual void set_manage(); // calls g_error()
#endif //DOXYGEN_SHOULD_SKIP_THIS

#ifndef DOXYGEN_SHOULD_SKIP_THIS
  friend class Glib::GSigConnectionNode; // for GSigConnectionNode::notify()
#endif
};

#ifndef DOXYGEN_SHOULD_SKIP_THIS

template <class PropertyType> inline
void ObjectBase::set_property(const Glib::ustring& property_name, const PropertyType& value)
{
  Glib::Value<PropertyType> property_value;
  property_value.init(Glib::Value<PropertyType>::value_type());

  property_value.set(value);
  this->set_property_value(property_name, property_value);
}

template <class PropertyType> inline
void ObjectBase::get_property(const Glib::ustring& property_name, PropertyType& value) const
{
  Glib::Value<PropertyType> property_value;
  property_value.init(Glib::Value<PropertyType>::value_type());

  this->get_property_value(property_name, property_value);

  value = property_value.get();
}

#endif /* DOXYGEN_SHOULD_SKIP_THIS */


bool _gobject_cppinstance_already_deleted(GObject* gobject);

} // namespace Glib


#endif /* _GLIBMM_OBJECTBASE_H */