~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to samples/ComponentInspector/ComponentInspector.Core/Src/ObjectBrowser/ObjectCreator.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// <file>
 
2
//     <copyright see="prj:///doc/copyright.txt"/>
 
3
//     <license see="prj:///doc/license.txt"/>
 
4
//     <owner name="Oakland Software Incorporated" email="general@oaklandsoftware.com"/>
 
5
//     <version>$Revision$</version>
 
6
// </file>
 
7
 
 
8
using System;
 
9
using System.Diagnostics;
 
10
using System.Drawing;
 
11
using System.IO;
 
12
using System.Reflection;
 
13
using System.Threading;
 
14
using System.Windows.Forms;
 
15
 
 
16
using NoGoop.Controls;
 
17
using NoGoop.Obj;
 
18
using NoGoop.ObjBrowser.Dialogs;
 
19
using NoGoop.ObjBrowser.Panels;
 
20
using NoGoop.ObjBrowser.TreeNodes;
 
21
using NoGoop.Util;
 
22
 
 
23
namespace NoGoop.ObjBrowser
 
24
{
 
25
        // Creates objects
 
26
        public class ObjectCreator
 
27
        {
 
28
                protected MethodInfo            _entryMethod;
 
29
                protected Object                _applThreadContext;
 
30
                protected FieldInfo             _applCurrentForm;
 
31
 
 
32
                protected IDragDropItem         _sourceNode;
 
33
                ObjectTreeNode                  _targetNode;
 
34
 
 
35
                protected static ObjectCreator  _objCreator;
 
36
                protected static bool           _asyncObjectCreation; 
 
37
 
 
38
                protected Form                  _waitingForAppDialog;
 
39
 
 
40
                public ObjectCreator()
 
41
                {
 
42
                }
 
43
 
 
44
                ConstructorInfo FindConstructor(ConstructorInfo[] constructors)
 
45
                {
 
46
                        ConstructorInfo constructor = null;
 
47
 
 
48
                        if (constructors.Length > 1) {
 
49
                                // Ask them to chose a constructor, if the
 
50
                                // constructor requires parameters, then select
 
51
                                // it and get out, otherwise go ahead.
 
52
                                constructor = ConstructorDialog.
 
53
                                        GetConstructor(constructors);
 
54
                                if (constructor != null &&
 
55
                                        constructor.GetParameters().Length != 0) {
 
56
                                        AssemblySupport.SelectAssyTab();
 
57
                                        MemberTreeNode.FindMember(constructor).PointToNode();
 
58
                                        return null;
 
59
                                }
 
60
                        }
 
61
                        else
 
62
                                constructor = constructors[0];
 
63
 
 
64
                        // This was cancelled
 
65
                        if (constructor == null)
 
66
                                return null;
 
67
 
 
68
                        // Since we need to get parameters, we can't finish
 
69
                        // this operation now, we refer then to the constructor
 
70
                        // that they should use and they can drag that 
 
71
                        // constructor where they want the object to do
 
72
                        if (constructor.GetParameters().Length != 0)
 
73
                        {
 
74
                                BrowserTreeNode selNode = 
 
75
                                        MemberTreeNode.FindMember(constructor);
 
76
                                ErrorDialog.
 
77
                                        Show("Please select the constructor member " +
 
78
                                                 "of this Type, fill in the parameters, " +
 
79
                                                 "and then drag " +
 
80
                                                 "the constructor to where you " +
 
81
                                                 "want this object " + 
 
82
                                                 "to be created.",
 
83
                                                 "Provide Parameters",
 
84
                                                 MessageBoxIcon.Information);
 
85
                                AssemblySupport.SelectAssyTab();
 
86
                                selNode.PointToNode();
 
87
                                return null;
 
88
                        }
 
89
                        return constructor;
 
90
                }
 
91
 
 
92
                // Thread that runs the entry point for the application
 
93
                void EntryRun()
 
94
                {
 
95
                        // Run the application in the specified directory
 
96
                        string dir = ComponentInspectorProperties.ApplicationWorkingDirectory;
 
97
                        Directory.CreateDirectory(dir);
 
98
                        Directory.SetCurrentDirectory(dir);
 
99
 
 
100
                        // Get the application thread context for this thread;
 
101
                        // This will create it if its not present
 
102
                        Type t = typeof(Application).GetNestedType("ThreadContext", ReflectionHelper.ALL_BINDINGS);
 
103
                        MethodInfo m = t.GetMethod("FromCurrent", ReflectionHelper.ALL_STATIC_BINDINGS);
 
104
                        _applCurrentForm = t.GetField("currentForm", ReflectionHelper.ALL_STATIC_BINDINGS);
 
105
                        _applThreadContext = m.Invoke(null, null);
 
106
 
 
107
                        try {
 
108
                                Object fieldPropValue;
 
109
 
 
110
                                // Call the main
 
111
                                object[] parameters = ObjectBrowser.ParamPanel.GetParameterValues(!Constants.IGNORE_EXCEPTION, ParamPanel.SET_MEMBER, out fieldPropValue);
 
112
                                _entryMethod.Invoke(null, parameters);
 
113
                        } catch (Exception ex) {
 
114
                                lock (_objCreator) {
 
115
                                        CloseWaitingForAppDialog();
 
116
                                }
 
117
                                _asyncObjectCreation = false;
 
118
 
 
119
                                Exception showException = ex;
 
120
                                // Remove the useless wrapper exception
 
121
                                if (showException is TargetInvocationException)
 
122
                                        showException = ex.InnerException;
 
123
 
 
124
                                ErrorDialog.Show(showException,
 
125
                                                                 "Error running entry point "
 
126
                                                                 + _entryMethod,
 
127
                                                                 MessageBoxIcon.Error);
 
128
                        }
 
129
                }
 
130
 
 
131
                void CreateFromEntry(Assembly assy)
 
132
                {
 
133
                        Thread t = null;
 
134
                        lock (this) {
 
135
                                _entryMethod = assy.EntryPoint;
 
136
 
 
137
                                ThreadStart start = new ThreadStart(EntryRun);
 
138
                                t = new Thread(start);
 
139
                                t.Start();
 
140
 
 
141
                                _asyncObjectCreation = true;
 
142
 
 
143
                           // Now indicate we are wating for the application to start.
 
144
                                _waitingForAppDialog = new WaitingForAppDialog();
 
145
                        }
 
146
 
 
147
                        _waitingForAppDialog.ShowDialog();
 
148
                        lock (this) {
 
149
                                // Only kill it if we are waiting for it still, the
 
150
                                // dialog is closed either by the cancel button, or
 
151
                                // by being closed when the app is up
 
152
                                if (_asyncObjectCreation) {
 
153
                                        // Cancel it
 
154
                                        _asyncObjectCreation = false;
 
155
                                        t.Abort();
 
156
                                }
 
157
                        }
 
158
                }
 
159
 
 
160
                const int SLEEP_TIME = 500;
 
161
 
 
162
                // This is called by idle to finish the case of running
 
163
                // an application in a different thread
 
164
                public static void CheckOutstandingCreation()
 
165
                {
 
166
                        if (_objCreator != null && _asyncObjectCreation) {
 
167
                                // Not ready yet, try again
 
168
                                if (_objCreator._applThreadContext == null) {
 
169
                                        Thread.Sleep(SLEEP_TIME);
 
170
                                        return;
 
171
                                }
 
172
 
 
173
                                Object obj = _objCreator._applCurrentForm.GetValue(_objCreator._applThreadContext);
 
174
 
 
175
                                // Not ready yet, try again
 
176
                                if (obj == null) {
 
177
                                        Thread.Sleep(SLEEP_TIME);
 
178
                                        return;
 
179
                                }
 
180
 
 
181
                                _objCreator.FinishObjectCreation(obj);
 
182
                                lock (_objCreator) {
 
183
                                        _asyncObjectCreation = false;
 
184
                                        _objCreator._waitingForAppDialog.Close();
 
185
                                }
 
186
                                _objCreator = null;
 
187
                        }
 
188
                }
 
189
 
 
190
                internal static ObjectInfo CreateObject(IDragDropItem sourceNode, ObjectTreeNode targetNode)
 
191
                {
 
192
                        ObjectCreator objCreator = new ObjectCreator();
 
193
                        _objCreator = objCreator;
 
194
                        return objCreator.CreateObjectInternal(sourceNode, targetNode);
 
195
                }
 
196
 
 
197
                internal const bool THROW = true;
 
198
 
 
199
                internal static bool CheckCreateType(Type t, IDragDropItem sourceNode, bool doThrow)
 
200
                {
 
201
                        if (t == null) {
 
202
                                String msg = "(This is a bug, please report this) "
 
203
                                        + "Unable to determine .NET type for " 
 
204
                                        + sourceNode + new StackTrace(true);
 
205
                                if (doThrow)
 
206
                                        throw new Exception(msg);
 
207
                                ErrorDialog.Show(msg,
 
208
                                                                "Unable to Determine Type",
 
209
                                                                 MessageBoxIcon.Error);
 
210
                                return false;
 
211
                        }
 
212
 
 
213
                        if (!t.IsClass || t.IsAbstract) {
 
214
                                String msg = "Cannot create an object of type " + t
 
215
                                        + " because it is not a class, "
 
216
                                        + "or is an abstract class";
 
217
                                if (doThrow)
 
218
                                        throw new Exception(msg);
 
219
                                ErrorDialog.Show(msg,
 
220
                                                                "Type is not Class",
 
221
                                                                 MessageBoxIcon.Error);
 
222
                                return false;
 
223
                        }
 
224
                        return true;
 
225
                }
 
226
 
 
227
                // Creates the object of the specified class, and wraps a tree node
 
228
                // around it
 
229
                ObjectInfo CreateObjectInternal(IDragDropItem sourceNode, ObjectTreeNode targetNode)
 
230
                {
 
231
                        _sourceNode = sourceNode;
 
232
                        _targetNode = targetNode;
 
233
 
 
234
                        Object obj = null;
 
235
                        ConstructorInfo constructor = null;
 
236
                        ConstructorInfo[] constructors = null;
 
237
 
 
238
                        try {
 
239
                                if (sourceNode is ITargetType && !((ITargetType)sourceNode).IsMember) {
 
240
                                        ITargetType targetTypeNode = (ITargetType)sourceNode;
 
241
                                        Type t = targetTypeNode.Type;
 
242
                                        if (!CheckCreateType(t, sourceNode, !THROW))
 
243
                                                return null;
 
244
 
 
245
                                        // String is a special case, we just do it with the
 
246
                                        // string parameter value
 
247
                                        if (t.Equals(typeof(String))) {
 
248
                                                ObjectBrowser.ParamPanel.GetParameterValues(!Constants.IGNORE_EXCEPTION, ParamPanel.SET_MEMBER, out obj);
 
249
                                        } else {
 
250
                                                constructors = t.GetConstructors(ReflectionHelper.ALL_BINDINGS);
 
251
                                                if (constructors.Length == 0) {
 
252
                                                        obj = Activator.CreateInstance(t);
 
253
                                                } else {
 
254
                                                        constructor = FindConstructor(constructors);
 
255
                                                        if (constructor == null)
 
256
                                                                return null;
 
257
                                                }
 
258
                                        }
 
259
                                } else if (sourceNode is MemberTreeNode) {
 
260
                                        constructor = (ConstructorInfo)((MemberTreeNode)sourceNode).Member;
 
261
                                } else if (sourceNode is AssemblyTreeNode) {
 
262
                                        CreateFromEntry(((AssemblyTreeNode)sourceNode).Assembly);
 
263
                                        // This gets finished when the event processing
 
264
                                        // is finished and we go to idle
 
265
                                        return null;
 
266
                                } else {
 
267
                                        throw new Exception("Bug: invalid node being dragged: " + sourceNode.GetType());
 
268
                                }
 
269
 
 
270
                                // Invoke the constructor with the parameters 
 
271
                                // defined in the param panel
 
272
                                if (obj == null) {
 
273
                                        Object fieldPropValue;
 
274
                                        obj = constructor.Invoke(ObjectBrowser.ParamPanel.GetParameterValues(!Constants.IGNORE_EXCEPTION,
 
275
                                                ParamPanel.SET_MEMBER, out fieldPropValue));
 
276
                                }
 
277
 
 
278
                                return FinishObjectCreation(obj);
 
279
                        } catch (Exception ex) {
 
280
                                Exception showException = ex;
 
281
                                // Remove the useless wrapper exception
 
282
                                if (showException is TargetInvocationException)
 
283
                                        showException = ex.InnerException;
 
284
 
 
285
                                ErrorDialog.Show(showException,
 
286
                                                                 "Error creating object",
 
287
                                                                 MessageBoxIcon.Error);
 
288
                                return null;
 
289
                        }
 
290
                }
 
291
 
 
292
                ObjectInfo FinishObjectCreation(Object obj)
 
293
                {
 
294
                        // Generate a name
 
295
                        if (obj is Control && !_asyncObjectCreation) {
 
296
                                Control c = (Control)obj;
 
297
                                c.Name = CompNumber.GetCompName(obj.GetType());
 
298
                                // This one can't have the text set to anything but a date
 
299
                                if (!(c is DateTimePicker))
 
300
                                        c.Text = c.Name;
 
301
                        }
 
302
 
 
303
                        ObjectInfo objInfo = _targetNode.AddNewObject(obj, _sourceNode);
 
304
 
 
305
                        // This is the case when the control is created not by dragging
 
306
                        // it to the design panel, but dragging it to the object
 
307
                        // tree somewhere
 
308
                        if (_sourceNode is IDesignSurfaceNode) {
 
309
                                IDesignSurfaceNode dNode = (IDesignSurfaceNode)_sourceNode;
 
310
                                if (obj is Control) {
 
311
                                        Control control = (Control)obj;
 
312
 
 
313
                                        // Some of them don't have them, need to pick something
 
314
                                        // so its visible
 
315
                                        Size defaultSize;
 
316
                                        
 
317
                                        PropertyInfo p = typeof(Control).GetProperty("DefaultSize", ReflectionHelper.ALL_BINDINGS);
 
318
                                        defaultSize = (Size)p.GetValue(control, null);
 
319
                                        if (defaultSize.Equals(Size.Empty)) {
 
320
                                                TraceUtil.WriteLineWarning(this, "No DefaultSize specified for " + control);
 
321
                                                control.Size = new Size(200, 200);
 
322
                                        }
 
323
 
 
324
                                        if (dNode.OnDesignSurface) {
 
325
                                                // Give the user a change with AxWebBrowser
 
326
                                                if (control.GetType().Name.Equals("AxWebBrowser")) {
 
327
                                                        ErrorDialog.Show
 
328
                                                                ("Before calling methods on the WebBrowser "
 
329
                                                                 + "object, please turn off Design Mode.  "
 
330
                                                                 + "This works around a known problem where "
 
331
                                                                 + "the browser control does not work "
 
332
                                                                 + "initially correctly in design mode.  "
 
333
                                                                 + "The problem only occurs on the "
 
334
                                                                 + "first method invocation; you may turn on "
 
335
                                                                 + "design mode after the first method call "
 
336
                                                                 + "is completely finished.",
 
337
                                                                 "Please turn off Design Mode",
 
338
                                                                 MessageBoxIcon.Warning);
 
339
                                                }
 
340
 
 
341
                                                try {
 
342
                                                        // The control may complain if it does not
 
343
                                                        // like where it is being added
 
344
                                                        ObjectBrowser.ImagePanel.AddControl(objInfo, control);
 
345
                                                } catch (Exception ex) {
 
346
                                                        _targetNode.RemoveObject(objInfo.Obj);
 
347
                                                        throw new Exception
 
348
                                                                ("There was an error adding this control " 
 
349
                                                                 + "to the design surface.  You might want "
 
350
                                                                 + "using the Action menu (right-click) "
 
351
                                                                 + "to not have the control created "
 
352
                                                                 + "on the design surface", ex);
 
353
                                                }
 
354
                                        }
 
355
                                        control.Show();
 
356
                                }
 
357
                        }
 
358
                        return objInfo;
 
359
                }
 
360
                
 
361
                void CloseWaitingForAppDialog()
 
362
                {
 
363
                        if (_waitingForAppDialog.InvokeRequired) {
 
364
                                _waitingForAppDialog.Invoke(new MethodInvoker(CloseWaitingForAppDialog));
 
365
                        } else {
 
366
                                Console.WriteLine("CloseWaitingForAppDialog");
 
367
                                _waitingForAppDialog.Close();
 
368
                        }
 
369
                }
 
370
        }
 
371
}