summaryrefslogtreecommitdiff
path: root/eel/eel-gtk-macros.h
blob: 2bf8e064fe7750066a27f2f206f393b09544ac64 (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
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-

   eel-gtk-macros.h: Macros to reduce boilerplate when using GTK.

   Copyright (C) 1999, 2000, 2001 Eazel, Inc.

   This program 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 program 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 program; if not, write to the
   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
   Boston, MA 02110-1301, USA.

   Authors: Darin Adler <darin@bentspoon.com>
            Ramiro Estrugo <ramiro@eazel.com>
*/

#ifndef EEL_GTK_MACROS_H
#define EEL_GTK_MACROS_H

#ifndef EEL_DISABLE_DEPRECATED

/* Define a parent_class global and a get_type function for a GTK class.
   Since this is boilerplate, it's better not to repeat it over and over again.
   Called like this:

       EEL_CLASS_BOILERPLATE (EelBookmark, eel_bookmark, GTK_TYPE_OBJECT)

   The parent_class_type parameter is guaranteed to be evaluated only once
   so it can be an expression, even an expression that contains a function call.
*/

#define EEL_CLASS_BOILERPLATE(class_name, prefix, parent_class_type)          \
	EEL_BOILERPLATE (class_name, class_name, prefix, parent_class_type,   \
                         EEL_REGISTER_TYPE)
#define EEL_REGISTER_TYPE(class_name, corba_name)                             \
	g_type_register_static (parent_type, #class_name, &info, 0)

#define EEL_BOILERPLATE(class_name, corba_name, prefix, parent_class_type,    \
                        register_type)                                        \
                                                                              \
static gpointer parent_class;                                                 \
                                                                              \
GType                                                                         \
prefix##_get_type (void)                                                      \
{                                                                             \
	GType parent_type;                                                    \
	static GType type;                                                    \
                                                                              \
	if (type == 0) {                                                      \
		static GTypeInfo info = {                                     \
			sizeof (class_name##Class),                           \
                        NULL, NULL,                                           \
			(GClassInitFunc) prefix##_class_init,                 \
                        NULL, NULL,                                           \
			sizeof (class_name), 0,                               \
			(GInstanceInitFunc) prefix##_init,                    \
			NULL                                                  \
		};                                                            \
                                                                              \
		parent_type = (parent_class_type);                            \
		type = register_type (class_name, corba_name);                \
		parent_class = g_type_class_ref (parent_type);                \
	}                                                                     \
                                                                              \
	return type;                                                          \
}

/* Call a parent class version of a virtual function (or default
 * signal handler since that's the same thing). Nice because it
 * documents what it's doing and there is less chance for a
 * typo. Depends on the parent class pointer having the conventional
 * name "parent_class" as the boilerplate macro above does it.
 */
#define EEL_CALL_PARENT(parent_class_cast_macro, signal, parameters)          \
                                                                              \
G_STMT_START {                                                                \
	if (parent_class_cast_macro (parent_class)->signal != NULL) {         \
		(* parent_class_cast_macro (parent_class)->signal) parameters;\
        }                                                                     \
} G_STMT_END

/* Same thing, for functions with a return value. */
#define EEL_CALL_PARENT_WITH_RETURN_VALUE(parent_class_cast_macro, signal,    \
                                          parameters)                         \
                                                                              \
(parent_class_cast_macro (parent_class)->signal == NULL)                      \
	? 0                                                                   \
	: ((* parent_class_cast_macro (parent_class)->signal) parameters)

#endif /* EEL_DISABLE_DEPRECATED */

/* Call a virtual function. Useful when the virtual function is not a
 * signal, otherwise you want to gtk_signal emit. Nice because it
 * documents what it's doing and there is less chance for a typo.
 */
#define EEL_CALL_METHOD(class_cast_macro, object, signal, parameters)         \
                                                                              \
G_STMT_START {                                                                \
	if (class_cast_macro (G_OBJECT_GET_CLASS (object))->signal != NULL) { \
		(* class_cast_macro (G_OBJECT_GET_CLASS (object))->signal)    \
                parameters;                                                   \
	}                                                                     \
} G_STMT_END

/* Same thing, for functions with a return value. */
#define EEL_CALL_METHOD_WITH_RETURN_VALUE(class_cast_macro, object, signal,   \
                                          parameters)                         \
                                                                              \
(class_cast_macro (G_OBJECT_GET_CLASS (object))->signal == NULL)              \
	? 0                                                                   \
	: ((* class_cast_macro (G_OBJECT_GET_CLASS (object))->signal)         \
           parameters)                                                        \
 
#ifndef G_DISABLE_ASSERT

/* Define a signal that is not implemented by this class but must be
 * implemented by subclasses. This macro should be used inside the
 * class initialization function. The companion macro EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL
 * must be used earlier in the file. Called like this:
 *
 * EEL_ASSIGN_MUST_OVERRIDE_SIGNAL (klass,
 *					 fm_directory_view,
 *					 clear);
 */
#define EEL_ASSIGN_MUST_OVERRIDE_SIGNAL(class_pointer, prefix, signal)        \
                                                                              \
* (void (**)(void)) & (class_pointer)->signal = prefix##_unimplemented_##signal

/* Provide a debug-only implementation of a signal that must be implemented
 * by subclasses. The debug-only implementation fires a warning if it is called.
 * This macro should be placed as if it were a function, earlier in the file
 * than the class initialization function. Called like this:
 *
 * EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL (fm_directory_view, clear);
 */
#define EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL(prefix, signal)                    \
                                                                              \
static void                                                                   \
prefix##_unimplemented_##signal (void)                                        \
{                                                                             \
	g_warning ("failed to override signal " #prefix "->" #signal);        \
}

#else /* G_DISABLE_ASSERT */

#define EEL_DEFINE_MUST_OVERRIDE_SIGNAL(class_cast_macro, class_pointer, prefix, signal)
#define EEL_IMPLEMENT_MUST_OVERRIDE_SIGNAL(prefix, signal)
#define EEL_ASSIGN_MUST_OVERRIDE_SIGNAL(class_pointer, prefix, signal)

#endif /* G_DISABLE_ASSERT */

/* Access a method. */
#define EEL_ACCESS_METHOD(class_cast_macro, object, method)                   \
(class_cast_macro (G_OBJECT_GET_CLASS (object))->method)

/* Invoke a method for a given object. */
#define EEL_INVOKE_METHOD(class_cast_macro, object, method, parameters)       \
((* EEL_ACCESS_METHOD (class_cast_macro, object, method)) parameters)

/* Assert the non-nullness of a method for a given object. */
#define EEL_ASSERT_METHOD(class_cast_macro, object, method)                   \
g_assert (EEL_ACCESS_METHOD (class_cast_macro, object, method) != NULL)

/* Invoke a method if it ain't null. */
#define EEL_INVOKE_METHOD_IF(class_cast_macro, object, method, parameters)    \
(EEL_ACCESS_METHOD (class_cast_macro, object, method) ? 0 :                   \
	EEL_INVOKE_METHOD (class_cast_macro, object, method, parameters))

#endif /* EEL_GTK_MACROS_H */