Support constructor chain up to GObject using Object (...)
[vala-lang.git] / vala / valasignal.vala
blob207d8f73742cf97ea7938477130461d7ec8506c3
1 /* valasignal.vala
3 * Copyright (C) 2006-2009 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 using GLib;
25 /**
26 * Represents an object signal. Signals enable objects to provide notifications.
28 public class Vala.Signal : Member, Lockable {
29 /**
30 * The return type of handlers of this signal.
32 public DataType return_type {
33 get { return _return_type; }
34 set {
35 _return_type = value;
36 _return_type.parent_node = this;
40 public Block body {
41 get { return _body; }
42 set {
43 _body = value;
44 if (_body != null) {
45 _body.owner = scope;
50 /**
51 * Specifies whether this signal has an emitter wrapper function.
53 public bool has_emitter { get; set; }
55 /**
56 * Specifies whether this signal has virtual method handler.
58 public bool is_virtual { get; set; }
60 private List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
61 /**
62 * Refers to the default signal handler, which is an anonymous
63 * function in the scope.
64 * */
65 public Method default_handler { get; private set; }
67 private string cname;
69 private bool lock_used = false;
71 private DataType _return_type;
73 private Block _body;
75 /**
76 * Creates a new signal.
78 * @param name signal name
79 * @param return_type signal return type
80 * @param source reference to source code
81 * @return newly created signal
83 public Signal (string name, DataType return_type, SourceReference? source_reference = null, Comment? comment = null) {
84 base (name, source_reference, comment);
85 this.return_type = return_type;
88 /**
89 * Appends parameter to signal handler.
91 * @param param a formal parameter
93 public void add_parameter (FormalParameter param) {
94 // default C parameter position
95 param.cparameter_position = parameters.size + 1;
96 param.carray_length_parameter_position = param.cparameter_position + 0.1;
97 param.cdelegate_target_parameter_position = param.cparameter_position + 0.1;
99 parameters.add (param);
100 scope.add (param.name, param);
103 public List<FormalParameter> get_parameters () {
104 return new ReadOnlyList<FormalParameter> (parameters);
108 * Returns generated delegate to be used for signal handlers.
110 * @return delegate
112 public Delegate get_delegate (DataType sender_type, CodeNode node_reference) {
113 var actual_return_type = return_type.get_actual_type (sender_type, null, node_reference);
115 var generated_delegate = new Delegate (null, actual_return_type);
116 generated_delegate.has_target = true;
117 generated_delegate.access = SymbolAccessibility.PUBLIC;
118 generated_delegate.owner = scope;
120 // sender parameter is never null and doesn't own its value
121 var sender_param_type = sender_type.copy ();
122 sender_param_type.value_owned = false;
123 sender_param_type.nullable = false;
125 generated_delegate.sender_type = sender_param_type;
127 foreach (FormalParameter param in parameters) {
128 var actual_param = param.copy ();
129 actual_param.parameter_type = actual_param.parameter_type.get_actual_type (sender_type, null, node_reference);
130 generated_delegate.add_parameter (actual_param);
133 scope.add (null, generated_delegate);
135 return generated_delegate;
139 * Returns the name of this signal as it is used in C code.
141 * @return the name to be used in C code
143 public string get_cname () {
144 if (cname == null) {
145 cname = camel_case_to_lower_case (name);
147 return cname;
150 public void set_cname (string cname) {
151 this.cname = cname;
155 * Returns the string literal of this signal to be used in C code.
157 * @return string literal to be used in C code
159 public CCodeConstant get_canonical_cconstant (string? detail = null) {
160 var str = new StringBuilder ("\"");
162 string i = get_cname ();
164 while (i.len () > 0) {
165 unichar c = i.get_char ();
166 if (c == '_') {
167 str.append_c ('-');
168 } else {
169 str.append_unichar (c);
172 i = i.next_char ();
175 if (detail != null) {
176 str.append ("::");
177 str.append (detail);
180 str.append_c ('"');
182 return new CCodeConstant (str.str);
185 public override void accept (CodeVisitor visitor) {
186 visitor.visit_member (this);
188 visitor.visit_signal (this);
191 public override void accept_children (CodeVisitor visitor) {
192 return_type.accept (visitor);
194 foreach (FormalParameter param in parameters) {
195 param.accept (visitor);
197 if (default_handler != null) {
198 default_handler.accept (visitor);
203 * Process all associated attributes.
205 public void process_attributes () {
206 foreach (Attribute a in attributes) {
207 if (a.name == "HasEmitter") {
208 has_emitter = true;
213 public bool get_lock_used () {
214 return lock_used;
217 public void set_lock_used (bool used) {
218 lock_used = used;
221 public override void replace_type (DataType old_type, DataType new_type) {
222 if (return_type == old_type) {
223 return_type = new_type;
227 public override bool check (SemanticAnalyzer analyzer) {
228 if (checked) {
229 return !error;
232 checked = true;
234 process_attributes ();
236 return_type.check (analyzer);
238 foreach (FormalParameter param in parameters) {
239 param.check (analyzer);
242 if (!is_virtual && body != null) {
243 Report.error (source_reference, "Only virtual signals can have a default signal handler body");
247 if (is_virtual) {
248 default_handler = new Method (name, return_type, source_reference);
250 default_handler.owner = owner;
251 default_handler.access = access;
252 default_handler.external = external;
253 default_handler.is_virtual = true;
254 default_handler.vfunc_name = name;
255 default_handler.signal_reference = this;
256 default_handler.body = body;
259 foreach (FormalParameter param in parameters) {
260 default_handler.add_parameter (param);
263 var cl = parent_symbol as Class;
265 cl.add_hidden_method (default_handler);
266 default_handler.check (analyzer);
270 if (!external_package && !hides && get_hidden_member () != null) {
271 Report.warning (source_reference, "%s hides inherited signal `%s'. Use the `new' keyword if hiding was intentional".printf (get_full_name (), get_hidden_member ().get_full_name ()));
274 return !error;