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>
9
using System.Diagnostics;
12
using System.Reflection;
13
using System.Threading;
14
using System.Windows.Forms;
16
using NoGoop.Controls;
18
using NoGoop.ObjBrowser.Dialogs;
19
using NoGoop.ObjBrowser.Panels;
20
using NoGoop.ObjBrowser.TreeNodes;
23
namespace NoGoop.ObjBrowser
26
public class ObjectCreator
28
protected MethodInfo _entryMethod;
29
protected Object _applThreadContext;
30
protected FieldInfo _applCurrentForm;
32
protected IDragDropItem _sourceNode;
33
ObjectTreeNode _targetNode;
35
protected static ObjectCreator _objCreator;
36
protected static bool _asyncObjectCreation;
38
protected Form _waitingForAppDialog;
40
public ObjectCreator()
44
ConstructorInfo FindConstructor(ConstructorInfo[] constructors)
46
ConstructorInfo constructor = null;
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();
62
constructor = constructors[0];
65
if (constructor == null)
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)
74
BrowserTreeNode selNode =
75
MemberTreeNode.FindMember(constructor);
77
Show("Please select the constructor member " +
78
"of this Type, fill in the parameters, " +
80
"the constructor to where you " +
84
MessageBoxIcon.Information);
85
AssemblySupport.SelectAssyTab();
86
selNode.PointToNode();
92
// Thread that runs the entry point for the application
95
// Run the application in the specified directory
96
string dir = ComponentInspectorProperties.ApplicationWorkingDirectory;
97
Directory.CreateDirectory(dir);
98
Directory.SetCurrentDirectory(dir);
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);
108
Object fieldPropValue;
111
object[] parameters = ObjectBrowser.ParamPanel.GetParameterValues(!Constants.IGNORE_EXCEPTION, ParamPanel.SET_MEMBER, out fieldPropValue);
112
_entryMethod.Invoke(null, parameters);
113
} catch (Exception ex) {
115
CloseWaitingForAppDialog();
117
_asyncObjectCreation = false;
119
Exception showException = ex;
120
// Remove the useless wrapper exception
121
if (showException is TargetInvocationException)
122
showException = ex.InnerException;
124
ErrorDialog.Show(showException,
125
"Error running entry point "
127
MessageBoxIcon.Error);
131
void CreateFromEntry(Assembly assy)
135
_entryMethod = assy.EntryPoint;
137
ThreadStart start = new ThreadStart(EntryRun);
138
t = new Thread(start);
141
_asyncObjectCreation = true;
143
// Now indicate we are wating for the application to start.
144
_waitingForAppDialog = new WaitingForAppDialog();
147
_waitingForAppDialog.ShowDialog();
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) {
154
_asyncObjectCreation = false;
160
const int SLEEP_TIME = 500;
162
// This is called by idle to finish the case of running
163
// an application in a different thread
164
public static void CheckOutstandingCreation()
166
if (_objCreator != null && _asyncObjectCreation) {
167
// Not ready yet, try again
168
if (_objCreator._applThreadContext == null) {
169
Thread.Sleep(SLEEP_TIME);
173
Object obj = _objCreator._applCurrentForm.GetValue(_objCreator._applThreadContext);
175
// Not ready yet, try again
177
Thread.Sleep(SLEEP_TIME);
181
_objCreator.FinishObjectCreation(obj);
183
_asyncObjectCreation = false;
184
_objCreator._waitingForAppDialog.Close();
190
internal static ObjectInfo CreateObject(IDragDropItem sourceNode, ObjectTreeNode targetNode)
192
ObjectCreator objCreator = new ObjectCreator();
193
_objCreator = objCreator;
194
return objCreator.CreateObjectInternal(sourceNode, targetNode);
197
internal const bool THROW = true;
199
internal static bool CheckCreateType(Type t, IDragDropItem sourceNode, bool doThrow)
202
String msg = "(This is a bug, please report this) "
203
+ "Unable to determine .NET type for "
204
+ sourceNode + new StackTrace(true);
206
throw new Exception(msg);
207
ErrorDialog.Show(msg,
208
"Unable to Determine Type",
209
MessageBoxIcon.Error);
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";
218
throw new Exception(msg);
219
ErrorDialog.Show(msg,
221
MessageBoxIcon.Error);
227
// Creates the object of the specified class, and wraps a tree node
229
ObjectInfo CreateObjectInternal(IDragDropItem sourceNode, ObjectTreeNode targetNode)
231
_sourceNode = sourceNode;
232
_targetNode = targetNode;
235
ConstructorInfo constructor = null;
236
ConstructorInfo[] constructors = null;
239
if (sourceNode is ITargetType && !((ITargetType)sourceNode).IsMember) {
240
ITargetType targetTypeNode = (ITargetType)sourceNode;
241
Type t = targetTypeNode.Type;
242
if (!CheckCreateType(t, sourceNode, !THROW))
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);
250
constructors = t.GetConstructors(ReflectionHelper.ALL_BINDINGS);
251
if (constructors.Length == 0) {
252
obj = Activator.CreateInstance(t);
254
constructor = FindConstructor(constructors);
255
if (constructor == null)
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
267
throw new Exception("Bug: invalid node being dragged: " + sourceNode.GetType());
270
// Invoke the constructor with the parameters
271
// defined in the param panel
273
Object fieldPropValue;
274
obj = constructor.Invoke(ObjectBrowser.ParamPanel.GetParameterValues(!Constants.IGNORE_EXCEPTION,
275
ParamPanel.SET_MEMBER, out fieldPropValue));
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;
285
ErrorDialog.Show(showException,
286
"Error creating object",
287
MessageBoxIcon.Error);
292
ObjectInfo FinishObjectCreation(Object obj)
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))
303
ObjectInfo objInfo = _targetNode.AddNewObject(obj, _sourceNode);
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
308
if (_sourceNode is IDesignSurfaceNode) {
309
IDesignSurfaceNode dNode = (IDesignSurfaceNode)_sourceNode;
310
if (obj is Control) {
311
Control control = (Control)obj;
313
// Some of them don't have them, need to pick something
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);
324
if (dNode.OnDesignSurface) {
325
// Give the user a change with AxWebBrowser
326
if (control.GetType().Name.Equals("AxWebBrowser")) {
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);
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);
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);
361
void CloseWaitingForAppDialog()
363
if (_waitingForAppDialog.InvokeRequired) {
364
_waitingForAppDialog.Invoke(new MethodInvoker(CloseWaitingForAppDialog));
366
Console.WriteLine("CloseWaitingForAppDialog");
367
_waitingForAppDialog.Close();