~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric-updates

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.GtkCore/lib/stetic/libsteticui/CodeGenerator.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-18 08:40:51 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090218084051-gh8m6ukvokbwj7cf
Tags: 1.9.2+dfsg-1ubuntu1
* Merge from Debian Experimental (LP: #330519), remaining Ubuntu changes:
  + debian/control:
    - Update for Gnome# 2.24
    - Add libmono-cairo1.0-cil to build-deps to fool pkg-config check

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
using System;
2
 
using System.Reflection;
3
 
using System.CodeDom;
4
 
using System.CodeDom.Compiler;
5
 
using System.Collections.Generic;
6
 
using System.IO;
7
 
using System.Collections;
8
 
 
9
 
namespace Stetic
10
 
{
11
 
        internal static class CodeGenerator
12
 
        {
13
 
                public static void GenerateProjectCode (string file, CodeDomProvider provider, GenerationOptions options, ProjectBackend[] projects)
14
 
                {
15
 
                        CodeGenerationResult res = GenerateProjectCode (options, projects);
16
 
                        
17
 
                        ICodeGenerator gen = provider.CreateGenerator ();
18
 
                        string basePath = Path.GetDirectoryName (file);
19
 
                        
20
 
                        foreach (SteticCompilationUnit unit in res.Units) {
21
 
                                string fname;
22
 
                                if (unit.Name.Length == 0)
23
 
                                        fname = file;
24
 
                                else
25
 
                                        fname = Path.Combine (basePath, unit.Name);
26
 
                                StreamWriter fileStream = new StreamWriter (fname);
27
 
                                try {
28
 
                                        gen.GenerateCodeFromCompileUnit (unit, fileStream, new CodeGeneratorOptions ());
29
 
                                } finally {
30
 
                                        fileStream.Close ();
31
 
                                }
32
 
                        }
33
 
                }
34
 
                
35
 
                public static CodeGenerationResult GenerateProjectCode (GenerationOptions options, ProjectBackend[] projects)
36
 
                {
37
 
                        ArrayList warningList = new ArrayList ();
38
 
                        
39
 
                        List<SteticCompilationUnit> units = new List<SteticCompilationUnit> ();
40
 
                        SteticCompilationUnit globalUnit = new SteticCompilationUnit ("");
41
 
                        units.Add (globalUnit);
42
 
                        
43
 
                        if (options == null)
44
 
                                options = new GenerationOptions ();
45
 
                        CodeNamespace globalNs = new CodeNamespace (options.GlobalNamespace);
46
 
                        globalUnit.Namespaces.Add (globalNs);
47
 
                        
48
 
                        // Global class
49
 
                        
50
 
                        CodeTypeDeclaration globalType = new CodeTypeDeclaration ("Gui");
51
 
                        globalType.Attributes = MemberAttributes.Private;
52
 
                        globalType.TypeAttributes = TypeAttributes.NestedAssembly;
53
 
                        globalNs.Types.Add (globalType);
54
 
                        
55
 
                        // Create the project initialization method
56
 
                        // This method will only be added at the end if there
57
 
                        // is actually something to initialize
58
 
                        
59
 
                        CodeMemberMethod initMethod = new CodeMemberMethod ();
60
 
                        initMethod.Name = "Initialize";
61
 
                        initMethod.ReturnType = new CodeTypeReference (typeof(void));
62
 
                        initMethod.Attributes = MemberAttributes.Assembly | MemberAttributes.Static;
63
 
                        initMethod.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Gtk.Widget), "iconRenderer"));
64
 
                        
65
 
                        GeneratorContext initContext = new ProjectGeneratorContext (globalNs, globalType, initMethod.Statements, options);
66
 
                        initContext.RootObject = new CodeArgumentReferenceExpression ("iconRenderer");
67
 
                        
68
 
                        // Generate icon factory creation
69
 
 
70
 
                        foreach (ProjectBackend gp in projects) {
71
 
                                if (gp.IconFactory.Icons.Count > 0)
72
 
                                        gp.IconFactory.GenerateBuildCode (initContext);
73
 
                        }
74
 
                        warningList.AddRange (initContext.Warnings);
75
 
                                        
76
 
                        // Generate the code
77
 
                        
78
 
                        if (options.UsePartialClasses)
79
 
                                CodeGeneratorPartialClass.GenerateProjectGuiCode (globalUnit, globalNs, globalType, options, units, projects, warningList);
80
 
                        else
81
 
                                CodeGeneratorInternalClass.GenerateProjectGuiCode (globalUnit, globalNs, globalType, options, units, projects, warningList);
82
 
 
83
 
                        GenerateProjectActionsCode (globalNs, options, projects);
84
 
                        
85
 
                        // Final step. If there is some initialization code, add all needed infrastructure
86
 
                        
87
 
                        globalType.Members.Add (initMethod);
88
 
                        
89
 
                        CodeMemberField initField = new CodeMemberField (typeof(bool), "initialized");
90
 
                        initField.Attributes = MemberAttributes.Private | MemberAttributes.Static;
91
 
                        globalType.Members.Add (initField);
92
 
                        
93
 
                        CodeFieldReferenceExpression initVar = new CodeFieldReferenceExpression (
94
 
                                new CodeTypeReferenceExpression (globalNs.Name + ".Gui"),
95
 
                                "initialized"
96
 
                        );
97
 
                        
98
 
                        CodeConditionStatement initCondition = new CodeConditionStatement ();
99
 
                        initCondition.Condition = new CodeBinaryOperatorExpression (
100
 
                                initVar, 
101
 
                                CodeBinaryOperatorType.IdentityEquality,
102
 
                                new CodePrimitiveExpression (false)
103
 
                        );
104
 
                        initCondition.TrueStatements.Add (new CodeAssignStatement (
105
 
                                initVar,
106
 
                                new CodePrimitiveExpression (true)
107
 
                        ));
108
 
                        initCondition.TrueStatements.AddRange (initMethod.Statements);
109
 
                        initMethod.Statements.Clear ();
110
 
                        initMethod.Statements.Add (initCondition);
111
 
                        
112
 
                        return new CodeGenerationResult (units.ToArray (), (string[]) warningList.ToArray (typeof(string)));
113
 
                }
114
 
                
115
 
                internal static void BindSignalHandlers (CodeExpression targetObjectVar, ObjectWrapper wrapper, Stetic.WidgetMap map, CodeStatementCollection statements, GenerationOptions options)
116
 
                {
117
 
                        foreach (Signal signal in wrapper.Signals) {
118
 
                                SignalDescriptor descriptor = signal.SignalDescriptor;
119
 
                                
120
 
                                CodeExpression createDelegate;
121
 
                                
122
 
                                if (options.UsePartialClasses) {
123
 
                                        createDelegate =
124
 
                                                new CodeDelegateCreateExpression (
125
 
                                                        new CodeTypeReference (descriptor.HandlerTypeName),
126
 
                                                        new CodeThisReferenceExpression (),
127
 
                                                        signal.Handler);
128
 
                                } else {
129
 
                                        createDelegate =
130
 
                                                new CodeMethodInvokeExpression (
131
 
                                                        new CodeTypeReferenceExpression (typeof(Delegate)),
132
 
                                                        "CreateDelegate",
133
 
                                                        new CodeTypeOfExpression (descriptor.HandlerTypeName),
134
 
                                                        targetObjectVar,
135
 
                                                        new CodePrimitiveExpression (signal.Handler));
136
 
                                        
137
 
                                        createDelegate = new CodeCastExpression (descriptor.HandlerTypeName, createDelegate);
138
 
                                }
139
 
                                
140
 
                                CodeAttachEventStatement cevent = new CodeAttachEventStatement (
141
 
                                        new CodeEventReferenceExpression (
142
 
                                                map.GetWidgetExp (wrapper),
143
 
                                                descriptor.Name),
144
 
                                        createDelegate);
145
 
                                
146
 
                                statements.Add (cevent);
147
 
                        }
148
 
                        
149
 
                        Wrapper.Widget widget = wrapper as Wrapper.Widget;
150
 
                        if (widget != null && widget.IsTopLevel) {
151
 
                                // Bind local action signals
152
 
                                foreach (Wrapper.ActionGroup grp in widget.LocalActionGroups) {
153
 
                                        foreach (Wrapper.Action ac in grp.Actions)
154
 
                                                BindSignalHandlers (targetObjectVar, ac, map, statements, options);
155
 
                                }
156
 
                        }
157
 
                        
158
 
                        Gtk.Container cont = wrapper.Wrapped as Gtk.Container;
159
 
                        if (cont != null) {
160
 
                                foreach (Gtk.Widget child in cont.AllChildren) {
161
 
                                        Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (child);
162
 
                                        if (ww != null)
163
 
                                                BindSignalHandlers (targetObjectVar, ww, map, statements, options);
164
 
                                }
165
 
                        }
166
 
                        
167
 
                }
168
 
                
169
 
                static void GenerateProjectActionsCode (CodeNamespace cns, GenerationOptions options, params ProjectBackend[] projects)
170
 
                {
171
 
                        bool multiProject = projects.Length > 1;
172
 
                        
173
 
                        CodeTypeDeclaration type = new CodeTypeDeclaration ("ActionGroups");
174
 
                        type.Attributes = MemberAttributes.Private;
175
 
                        type.TypeAttributes = TypeAttributes.NestedAssembly;
176
 
                        cns.Types.Add (type);
177
 
 
178
 
                        // Generate the global action group getter
179
 
                        
180
 
                        CodeMemberMethod met = new CodeMemberMethod ();
181
 
                        met.Name = "GetActionGroup";
182
 
                        type.Members.Add (met);
183
 
                        met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(Type), "type"));
184
 
                        if (multiProject)
185
 
                                met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file"));
186
 
                        met.ReturnType = new CodeTypeReference (typeof(Gtk.ActionGroup));
187
 
                        met.Attributes = MemberAttributes.Public | MemberAttributes.Static;
188
 
 
189
 
                        CodeMethodInvokeExpression call = new CodeMethodInvokeExpression (
190
 
                                        new CodeMethodReferenceExpression (
191
 
                                                new CodeTypeReferenceExpression (cns.Name + ".ActionGroups"),
192
 
                                                "GetActionGroup"
193
 
                                        ),
194
 
                                        new CodePropertyReferenceExpression (
195
 
                                                new CodeArgumentReferenceExpression ("type"),
196
 
                                                "FullName"
197
 
                                        )
198
 
                        );
199
 
                        if (multiProject)
200
 
                                call.Parameters.Add (new CodeArgumentReferenceExpression ("file"));
201
 
                                
202
 
                        met.Statements.Add (new CodeMethodReturnStatement (call));
203
 
 
204
 
                        // Generate the global action group getter (overload)
205
 
                        
206
 
                        met = new CodeMemberMethod ();
207
 
                        met.Name = "GetActionGroup";
208
 
                        type.Members.Add (met);
209
 
                        met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "name"));
210
 
                        if (multiProject)
211
 
                                met.Parameters.Add (new CodeParameterDeclarationExpression (typeof(string), "file"));
212
 
                        met.ReturnType = new CodeTypeReference (typeof(Gtk.ActionGroup));
213
 
                        met.Attributes = MemberAttributes.Public | MemberAttributes.Static;
214
 
                        
215
 
                        CodeArgumentReferenceExpression cfile = new CodeArgumentReferenceExpression ("file");
216
 
                        CodeArgumentReferenceExpression cid = new CodeArgumentReferenceExpression ("name");
217
 
                        
218
 
                        CodeStatementCollection projectCol = met.Statements;
219
 
                        int n=1;
220
 
                        
221
 
                        foreach (ProjectBackend gp in projects) {
222
 
                        
223
 
                                CodeStatementCollection widgetCol;
224
 
                                
225
 
                                if (multiProject) {
226
 
                                        CodeConditionStatement pcond = new CodeConditionStatement ();
227
 
                                        pcond.Condition = new CodeBinaryOperatorExpression (
228
 
                                                cfile, 
229
 
                                                CodeBinaryOperatorType.IdentityEquality,
230
 
                                                new CodePrimitiveExpression (gp.Id)
231
 
                                        );
232
 
                                        projectCol.Add (pcond);
233
 
                                        
234
 
                                        widgetCol = pcond.TrueStatements;
235
 
                                        projectCol = pcond.FalseStatements;
236
 
                                } else {
237
 
                                        widgetCol = projectCol;
238
 
                                }
239
 
                                
240
 
                                foreach (Wrapper.ActionGroup grp in gp.ActionGroups) {
241
 
                                        string fname = "group" + (n++);
242
 
                                        CodeMemberField grpField = new CodeMemberField (typeof(Gtk.ActionGroup), fname);
243
 
                                        grpField.Attributes |= MemberAttributes.Static;
244
 
                                        type.Members.Add (grpField);
245
 
                                        CodeFieldReferenceExpression grpVar = new CodeFieldReferenceExpression (
246
 
                                                new CodeTypeReferenceExpression (cns.Name + ".ActionGroups"),
247
 
                                                fname
248
 
                                        );
249
 
                                        
250
 
                                        CodeConditionStatement pcond = new CodeConditionStatement ();
251
 
                                        pcond.Condition = new CodeBinaryOperatorExpression (
252
 
                                                cid, 
253
 
                                                CodeBinaryOperatorType.IdentityEquality,
254
 
                                                new CodePrimitiveExpression (grp.Name)
255
 
                                        );
256
 
                                        widgetCol.Add (pcond);
257
 
                                        
258
 
                                        // If the group has not yet been created, create it
259
 
                                        CodeConditionStatement pcondGrp = new CodeConditionStatement ();
260
 
                                        pcondGrp.Condition = new CodeBinaryOperatorExpression (
261
 
                                                grpVar, 
262
 
                                                CodeBinaryOperatorType.IdentityEquality,
263
 
                                                new CodePrimitiveExpression (null)
264
 
                                        );
265
 
                                        
266
 
                                        pcondGrp.TrueStatements.Add (
267
 
                                                new CodeAssignStatement (
268
 
                                                        grpVar,
269
 
                                                        new CodeObjectCreateExpression (grp.Name)
270
 
                                                )
271
 
                                        );
272
 
                                        
273
 
                                        pcond.TrueStatements.Add (pcondGrp);
274
 
                                        pcond.TrueStatements.Add (new CodeMethodReturnStatement (grpVar));
275
 
                                        
276
 
                                        widgetCol = pcond.FalseStatements;
277
 
                                }
278
 
                                widgetCol.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (null)));
279
 
                        }
280
 
                        if (met.Statements.Count == 0)
281
 
                                met.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (null)));
282
 
                }
283
 
                
284
 
                internal static List<ObjectBindInfo> GetFieldsToBind (ObjectWrapper wrapper)
285
 
                {
286
 
                        List<ObjectBindInfo> tobind = new List<ObjectBindInfo> ();
287
 
                        GetFieldsToBind (tobind, wrapper);
288
 
                        return tobind;
289
 
                }
290
 
                
291
 
                static void GetFieldsToBind (List<ObjectBindInfo> tobind, ObjectWrapper wrapper)
292
 
                {
293
 
                        string memberName = null;
294
 
                        
295
 
                        if (wrapper is Wrapper.Widget) {
296
 
                                Wrapper.Widget ww = wrapper as Wrapper.Widget;
297
 
 
298
 
                                if (!ww.IsTopLevel && ww.InternalChildProperty == null && !ww.Unselectable)
299
 
                                        memberName = ((Wrapper.Widget) wrapper).Wrapped.Name;
300
 
                        }
301
 
                        else if (wrapper is Wrapper.Action)
302
 
                                memberName = ((Wrapper.Action) wrapper).Name;
303
 
                        
304
 
                        if (memberName != null) {
305
 
                                ObjectBindInfo binfo = new ObjectBindInfo (wrapper.WrappedTypeName, memberName);
306
 
                                tobind.Add (binfo);
307
 
                        }
308
 
                        
309
 
                        Wrapper.ActionGroup agroup = wrapper as Wrapper.ActionGroup;
310
 
                        if (agroup != null) {
311
 
                                foreach (Wrapper.Action ac in agroup.Actions)
312
 
                                        GetFieldsToBind (tobind, ac);
313
 
                        }
314
 
                        
315
 
                        Wrapper.Widget widget = wrapper as Wrapper.Widget;
316
 
                        if (widget != null && widget.IsTopLevel) {
317
 
                                // Generate fields for local actions
318
 
                                foreach (Wrapper.ActionGroup grp in widget.LocalActionGroups) {
319
 
                                        GetFieldsToBind (tobind, grp);
320
 
                                }
321
 
                        }
322
 
                        
323
 
                        Gtk.Container cont = wrapper.Wrapped as Gtk.Container;
324
 
                        if (cont != null) {
325
 
                                foreach (Gtk.Widget child in cont.AllChildren) {
326
 
                                        Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (child);
327
 
                                        if (ww != null)
328
 
                                                GetFieldsToBind (tobind, ww);
329
 
                                }
330
 
                        }
331
 
                }
332
 
                
333
 
                public static WidgetMap GenerateCreationCode (CodeNamespace cns, CodeTypeDeclaration type, Gtk.Widget w, CodeExpression widgetVarExp, CodeStatementCollection statements, GenerationOptions options, ArrayList warnings)
334
 
                {
335
 
                        statements.Add (new CodeCommentStatement ("Widget " + w.Name));
336
 
                        GeneratorContext ctx = new ProjectGeneratorContext (cns, type, statements, options);
337
 
                        Stetic.Wrapper.Widget ww = Stetic.Wrapper.Widget.Lookup (w);
338
 
                        ctx.GenerateCreationCode (ww, widgetVarExp);
339
 
                        ctx.EndGeneration ();
340
 
                        warnings.AddRange (ctx.Warnings);
341
 
                        return ctx.WidgetMap;
342
 
                }
343
 
                
344
 
                public static WidgetMap GenerateCreationCode (CodeNamespace cns, CodeTypeDeclaration type, Wrapper.ActionGroup grp, CodeExpression groupVarExp, CodeStatementCollection statements, GenerationOptions options, ArrayList warnings)
345
 
                {
346
 
                        statements.Add (new CodeCommentStatement ("Action group " + grp.Name));
347
 
                        GeneratorContext ctx = new ProjectGeneratorContext (cns, type, statements, options);
348
 
                        ctx.GenerateCreationCode (grp, groupVarExp);
349
 
                        ctx.EndGeneration ();
350
 
                        warnings.AddRange (ctx.Warnings);
351
 
                        return ctx.WidgetMap;
352
 
                }
353
 
        }
354
 
        
355
 
        class ProjectGeneratorContext: GeneratorContext
356
 
        {
357
 
                CodeTypeDeclaration type;
358
 
                
359
 
                public ProjectGeneratorContext (CodeNamespace cns, CodeTypeDeclaration type, CodeStatementCollection statements, GenerationOptions options): base (cns, "w", statements, options)
360
 
                {
361
 
                        this.type = type;
362
 
                }
363
 
                
364
 
                public override CodeExpression GenerateInstanceExpression (ObjectWrapper wrapper, CodeExpression newObject)
365
 
                {
366
 
                        string typeName = wrapper.WrappedTypeName;
367
 
                        string memberName = null;
368
 
                        if (wrapper is Wrapper.Widget)
369
 
                                memberName = ((Wrapper.Widget) wrapper).Wrapped.Name;
370
 
                        else if (wrapper is Wrapper.Action)
371
 
                                memberName = ((Wrapper.Action) wrapper).Name;
372
 
                        
373
 
                        if (memberName == null)
374
 
                                return base.GenerateInstanceExpression (wrapper, newObject);
375
 
                        
376
 
                        if (Options.UsePartialClasses) {
377
 
                                // Don't generate fields for top level widgets and for widgets accessible
378
 
                                // through other widget's properties
379
 
                                Wrapper.Widget ww = wrapper as Wrapper.Widget;
380
 
                                if (ww == null || (!ww.IsTopLevel && ww.InternalChildProperty == null && !ww.Unselectable)) {
381
 
                                        type.Members.Add (
382
 
                                                new CodeMemberField (
383
 
                                                        typeName,
384
 
                                                        memberName
385
 
                                                )
386
 
                                        );
387
 
                                        CodeExpression var = new CodeFieldReferenceExpression (
388
 
                                                                  new CodeThisReferenceExpression (),
389
 
                                                                  memberName
390
 
                                        );
391
 
 
392
 
                                        Statements.Add (
393
 
                                                new CodeAssignStatement (
394
 
                                                        var,
395
 
                                                        newObject
396
 
                                                )
397
 
                                        );
398
 
                                        return var;
399
 
                                }
400
 
                                else
401
 
                                        return base.GenerateInstanceExpression (wrapper, newObject);
402
 
                        } else {
403
 
                                CodeExpression var = base.GenerateInstanceExpression (wrapper, newObject);
404
 
                                Statements.Add (
405
 
                                        new CodeAssignStatement (
406
 
                                                new CodeIndexerExpression (
407
 
                                                        new CodeVariableReferenceExpression ("bindings"),
408
 
                                                        new CodePrimitiveExpression (memberName)
409
 
                                                ),
410
 
                                                var
411
 
                                        )
412
 
                                );
413
 
                                return var;
414
 
                        }
415
 
                }
416
 
        }
417
 
        
418
 
        [Serializable]
419
 
        public class SteticCompilationUnit: CodeCompileUnit
420
 
        {
421
 
                string name;
422
 
                
423
 
                public SteticCompilationUnit (string name)
424
 
                {
425
 
                        this.name = name;
426
 
                }
427
 
                
428
 
                public string Name {
429
 
                        get { return name; }
430
 
                        internal set { name = value; }
431
 
                }
432
 
        }
433
 
}