//ICloneable interface implementation: public object Clone() { Style clone = new Style(); clone.CopyAttributesFrom(this); if(m_properties != null) { clone.m_properties = new ArrayList(); for(int i = 0; i < m_properties.Count; i++) { IUimlElement element = (IUimlElement)m_properties[i]; clone.m_properties.Add(element.Clone()); } } return clone; }
///<summary> /// This is the ``core'' rendering method. It will recursively descend into the Part hierarchy /// and using the .net reflection mechanisms to create the appropriate widgets ///</summary> private Window Render(Part uiPart, Style uiStyle, Window parent) //throws WrongNestingException, MappingNotFoundException { string className = Voc.MapsOnCls(uiPart.Class); Type classType = GuiAssembly.GetType(className); Type containerType = GuiAssembly.GetType(CONTAINER); System.Object wxObject; // try{ // Console.WriteLine("Try to create instance for {0}", classType); // wxObject = Activator.CreateInstance(classType); // Console.WriteLine("Created object {0}", wxObject); // } // catch(MissingMethodException mme) { if(classType.Equals(containerType)) wxObject = CreateLayoutWithParams(classType, uiPart, uiStyle); else wxObject = CreateWithParams(classType, uiPart, uiStyle, parent); } //attach it to the Part for later manipulation uiPart.UiObject = wxObject; if(uiPart.HasSubParts()) { if(classType.Equals(containerType)) { m_adder = ADD; IEnumerator enumParts = uiPart.GetSubParts(); Window wxContainer = new Panel(parent); while(enumParts.MoveNext()) { Part subPart = (Part)enumParts.Current; Window b = Render(subPart, uiStyle, wxContainer); MethodInfo m = classType.GetMethod(m_adder, new Type[] { b.GetType() } ); m.Invoke(wxObject, new System.Object[] { b }); } PropertyInfo addLayout = typeof(Window).GetProperty(APPLY_LAYOUT /*, new Type[] { classType }*/ ); addLayout.SetValue(wxContainer, wxObject, null ); wxContainer.Fit(); return (Window)ApplyProperties((Window)wxContainer, uiPart, uiStyle); } else { throw new WrongNestingException(className, CONTAINER); } } else { //wxObject = AttachEvents((Widget)wxObject, uiBehavior); return (Window)ApplyProperties((Window)wxObject, uiPart, uiStyle); } }
///<summary> /// Applies several properties to an individual concrete widget instance /// relying on hard-coded knowledge about the widgets ///</summary> protected override System.Object LoadAdHocProperties(ref System.Object uiObject, Part part, Style s) { // Still not necessary :-) return uiObject; }
///<summary> /// This method is used when the classType does not contain a parameterless /// constructor. It searches for the first constructor that ``fits'' and /// according to the defined Style in uiStyle for the uiPart. ///</summary> private Window CreateWithParams(Type classType, Part uiPart, Style uiStyle, Window parent) { System.Object wxObject = null; Param[] parameters = Voc.GetParams(CONSTRUCTOR, uiPart.Class); Type[] tparamTypes = new Type[parameters.Length + 1]; tparamTypes[0] = typeof(Window); int i = 1; foreach(Param p in parameters) { int j = 0; while(tparamTypes[i] == null) { try { tparamTypes[i] = ((Assembly)ExternalLibraries.Instance.Assemblies[j++]).GetType(p.Type, true, true); } catch(TypeLoadException tle) { } catch { Console.WriteLine("Error in vocabulary: parameter {3} of type {0} for constructor of {1} is specified incorrect for part {2}", p.Type, uiPart.Class, uiPart.Identifier, p.Identifier); Environment.Exit(-1); } } i++; } ConstructorInfo construct = classType.GetConstructor(tparamTypes); if(construct == null) { Console.WriteLine("Error in vocabulary: constructor for {0} is not correctly defined.", uiPart.Class); Environment.Exit(-1); } Property[] tempProps = uiStyle.GetProperties(uiPart.Identifier, parameters); Property[] props = new Property[tempProps.Length + 1]; for(int teller=1; teller< props.Length; teller++) props[teller] = tempProps[teller-1]; if(props.Length-1 != parameters.Length) { String paramsString = ""; for(int j=0; j< parameters.Length; j++) paramsString += parameters[j].Identifier + ":" + parameters[j].Type + ", "; Console.WriteLine("Error in uiml document: required properties \"{0}\" are not available for {1} ({2})", paramsString, uiPart.Identifier, uiPart.Class); Environment.Exit(-1); return null; //useless statement } else { //if the first type is Window, insert "parent" in props[0] if( tparamTypes[0].Equals(typeof(Window))) { props[0] = new Property(); props[0].Name = "window"; props[0].PartName = "wx.Window"; props[0].PartName = "wx.Window"; props[0].Value = parent; } //create the arguments for the constructor from the property array //and pass it to the constuctor immediately try{ return (Window)construct.Invoke(Decoder.GetMultipleArgs(props,tparamTypes));} catch { //TODO: remove redundant statements!! String paramsString = ""; for(int j=0; j< parameters.Length; j++) paramsString += parameters[j].Identifier + ":" + parameters[j].Type + ", "; Console.WriteLine("Error in uiml document: required properties \"{0}\" are not available for {1} ({2})", paramsString, uiPart.Identifier, uiPart.Class); Environment.Exit(-1); return null; //useless statement } } }
///<summary> /// This method is used when the classType does not contain a parameterless /// constructor. It searches for the first constructor that ``fits'' and /// according to the defined Style in uiStyle for the uiPart. ///</summary> private System.Object CreateLayoutWithParams(Type classType, Part uiPart, Style uiStyle) { Param[] parameters = Voc.GetParams(CONSTRUCTOR, uiPart.Class); Type[] tparamTypes = new Type[parameters.Length]; int i = 0; foreach(Param p in parameters) { int j = 0; while(tparamTypes[i] == null) { try { tparamTypes[i] = ((Assembly)ExternalLibraries.Instance.Assemblies[j++]).GetType(p.Type, true, true); } catch(TypeLoadException tle) { } catch(Exception aiobe)//replace by ArrayIndexOutOfBounds { Console.WriteLine("Error in vocabulary: parameter {3} of type {0} for constructor of {1} is specified incorrect for part {2}", p.Type, uiPart.Class, uiPart.Identifier, p.Identifier); Environment.Exit(-1); } } i++; } ConstructorInfo construct = classType.GetConstructor(tparamTypes); if(construct == null) { Console.WriteLine("Error in vocabulary: constructor for {0} is not correctly defined.", uiPart.Class); Environment.Exit(-1); } Property[] props = null; if(uiStyle != null) props = uiStyle.GetProperties(uiPart.Identifier, parameters); if(props.Length != parameters.Length) { String paramsString = ""; for(int j=0; j< parameters.Length; j++) paramsString += parameters[j].Identifier + ":" + parameters[j].Type + ", "; Console.WriteLine("Error in uiml document: required properties \"{0}\" are not available for {1} ({2})", paramsString, uiPart.Identifier, uiPart.Class); Environment.Exit(-1); return null; //useless statement } else { //create the arguments for the constructor from the property array //and pass it to the constuctor immediately try{ return construct.Invoke(Decoder.GetMultipleArgs(props,tparamTypes));} catch { //TODO: remove redundant statements!! String paramsString = ""; for(int j=0; j< parameters.Length; j++) paramsString += parameters[j].Identifier + ":" + parameters[j].Type + ", "; Console.WriteLine("Error in uiml document: required properties \"{0}\" are not available for {1} ({2})", paramsString, uiPart.Identifier, uiPart.Class); Environment.Exit(-1); return null; //useless statement } } }
/* Moved to super class ///<summary> /// Dissects the method information for a specific property ///</summary> ///<param name="baseT"></param> ///<param name="newT"></param> ///<param name="retType"></param> ///<param name="nextValue"></param> private MemberInfo ResolveProperty(Type baseT, String newT, out Type retType, ref System.Object nextValue) { MemberInfo m = baseT.GetProperty(newT); if(m == null) { m = baseT.GetMethod(newT, new Type[0]); retType = ((MethodInfo)m).ReturnType; nextValue = ((MethodInfo)m).Invoke(nextValue, null); } else { retType = ((PropertyInfo)m).PropertyType; nextValue = ((PropertyInfo)m).GetValue(nextValue, null); } return m; } */ ///<summary> /// Applies several properties to an individual concrete widget instance /// relying on hard-coded knowledge about the widgets ///</summary> ///<todo> // Change to the .custom format, like used for the gtk# bindings ///</todo> protected override System.Object LoadAdHocProperties(ref System.Object uiObject, Part part, Style s) { // emulate the Items.AddRange() functionality Property prop = s.SearchProperty(part.Identifier, "content"); if(prop != null) { if(prop.Lazy) prop.Resolve(this); Param[] paramTypes = Voc.GetParams(prop.Name, part.Class); //convert the params to types Type[] tparamTypes = new Type[paramTypes.Length]; for(int i = 0; i < paramTypes.Length; i++) { tparamTypes[i] = null; int k = 0; while(tparamTypes[i] == null) tparamTypes[i] = ((Assembly)ExternalLibraries.Instance.Assemblies[k++]).GetType(paramTypes[i].Type); } System.Object[] blaai = TypeDecoder.Instance.GetArgs(prop, tparamTypes); string[] content = (string[])blaai[0]; switch(part.Class) { case "Combo": ComboBox cmb = (ComboBox) uiObject; for(int i = 0; i < content.Length; i++) { cmb.Items.Add(content[i]); } return cmb; case "ListBox": ListBox lb = (ListBox) uiObject; for(int i = 0; i < paramTypes.Length; i++) { lb.Items.Add(paramTypes[i].Value); } return lb; case "List": ListView lv = (ListView) uiObject; for(int i = 0; i < paramTypes.Length; i++) { lv.Items.Add(new ListViewItem(paramTypes[i].Value)); } return lv; } } return uiObject; }
///<summary> /// This is the ``core'' rendering method. It will recursively descend into the Part hierarchy /// and using the .net reflection mechanisms to create the appropriate widgets ///</summary> public Control Render(Part uiPart, Style uiStyle) //throws WrongNestingException, MappingNotFoundException { string className = Voc.MapsOnCls(uiPart.Class); Type classType = GuiAssembly.GetType(className); Type containerType = GuiAssembly.GetType(CONTAINER); object swfObject = (Activator.CreateInstance(classType)); //attach it to the Part for later manipulation uiPart.UiObject = swfObject; if(uiPart.HasSubParts()) { if(classType.IsSubclassOf(containerType)) { IEnumerator enumParts = uiPart.GetSubParts(); while(enumParts.MoveNext()) { Part subPart = (Part)enumParts.Current; Control b = Render(subPart, uiStyle); // add b to swfObject PropertyInfo p = classType.GetProperty(m_addProperty); Control.ControlCollection controls = (Control.ControlCollection)p.GetValue(swfObject, null); MethodInfo m = controls.GetType().GetMethod(m_addMethod, new Type[] { b.GetType() } ); m.Invoke(controls, new System.Object[] { b }); } return (Control)ApplyProperties((Control)swfObject, uiPart, uiStyle); } else { throw new WrongNestingException(className, CONTAINER); } } else { try { return (Control) ApplyProperties((Control)swfObject, uiPart, uiStyle); } catch(Exception e) { Console.WriteLine("Waaaaahhhgggrrr!:{0}",e); Console.WriteLine(swfObject.GetType().ToString()); return null; } } }
///<summary> /// Applies several properties to an individual concrete widget instance /// relying on hard-coded knowledge about the widgets, after /// all the other properties have been set first. ///</summary> ///<param name="UiObject"></param> ///<param name="part"></param> ///<param name"s"></param> protected override System.Object LoadAdHocPropertiesAfter(ref System.Object uiObject, Part part, Style s) { if(part.Class == "Tree" || part.Class == "List") { Property p = s.SearchProperty(part.Identifier, "title"); Gtk.TreeView tree = (Gtk.TreeView) uiObject; if (p == null) { // add an empty column Gtk.TreeViewColumn column = new Gtk.TreeViewColumn(); column.Title = (string) p.Value; tree.AppendColumn(column); } for (int i = 0; i < tree.Columns.Length; i++) { Gtk.TreeViewColumn col = tree.Columns[i]; Gtk.CellRendererText crt = new Gtk.CellRendererText(); col.PackStart(crt, true); col.AddAttribute(crt, "text", i); } tree.HeadersVisible = true; } return uiObject; }
/* moved to super class ///<summary> /// Dissects the method information for a specific property ///</summary> ///<param name="baseT"></param> ///<param name="newT"></param> ///<param name="retType"></param> ///<param name="nextValue"></param> private MemberInfo ResolveProperty(Type baseT, String newT, out Type retType, ref System.Object nextValue) { MemberInfo m = baseT.GetProperty(newT); if(m == null) { m = baseT.GetMethod(newT, new Type[0]); retType = ((MethodInfo)m).ReturnType; nextValue = ((MethodInfo)m).Invoke(nextValue, null); } else { retType = ((PropertyInfo)m).PropertyType; nextValue = ((PropertyInfo)m).GetValue(nextValue, null); } return m; } */ ///<summary> /// Applies several properties to an individual concrete widget instance /// relying on hard-coded knowledge about the widgets ///</summary> ///<param name="UiObject"></param> ///<param name="part"></param> ///<param name"s"></param> ///<todo> // Change to the .custom format, like used for the gtk# bindings ///</todo> protected override System.Object LoadAdHocProperties(ref System.Object uiObject, Part part, Style s) { if(part.Class == "TabPage") { /* FIXME: this implementation does not work because the TabPage has not yet been added * to the Tabs parent! */ Property p = s.SearchProperty(part.Identifier, "label"); string label; if(p != null) label = (string)p.Value; else label = ""; if(!part.Top) // if we have a parent { Notebook n = (Notebook)part.Parent.UiObject; n.SetTabLabelText((Widget)part.UiObject, label); } } return uiObject; }
///<summary> /// This is the ``core'' rendering method. It will recursively descend into the Part hierarchy /// and using the .net reflection mechanisms to create the appropriate widgets ///</summary> private Widget Render(Part uiPart, Style uiStyle) //throws WrongNestingException, MappingNotFoundException { string className = Voc.MapsOnCls(uiPart.Class); Type classType = GuiAssembly.GetType(className); Type containerType = GuiAssembly.GetType(CONTAINER); bool layoutWidget = DoesLayout(classType); System.Object gtkObject; try { if(layoutWidget) gtkObject = Activator.CreateInstance(classType, new System.Object[] { HOMOGENEOUS, SPACING} ); else gtkObject = Activator.CreateInstance(classType); } catch(MissingMethodException mme) { gtkObject = CreateWithParams(classType, uiPart, uiStyle); } //attach it to the Part for later manipulation uiPart.UiObject = gtkObject; if(uiPart.HasSubParts()) { if(classType.IsSubclassOf(containerType)) { //if(layoutWidget)//this is layout code // m_adder = PACKSTART; //else m_adder = ADD; IEnumerator enumParts = uiPart.GetSubParts(); while(enumParts.MoveNext()) { Part subPart = (Part)enumParts.Current; if (subPart.Identifier == "textfield2") { int zz = 0; } Widget b = Render(subPart, uiStyle); //((Container)gtkObject).Add(b); replaced by: MethodInfo m = classType.GetMethod(m_adder, new Type[] { b.GetType() } ); m.Invoke(gtkObject, new System.Object[] { b }); } return (Container)ApplyProperties((Container)gtkObject, uiPart, uiStyle); } else { throw new WrongNestingException(className, CONTAINER); } } else { //gtkObject = AttachEvents((Widget)gtkObject, uiBehavior); return (Widget)ApplyProperties((Widget)gtkObject, uiPart, uiStyle); } }
/// <summary> /// Used to set ad-hoc properties after the other properties /// have been set. /// </summary> virtual protected System.Object LoadAdHocPropertiesAfter(ref System.Object uiObject, Part part, Style s) { return null; }
abstract protected System.Object LoadAdHocProperties(ref System.Object uiObject, Part part, Style s);
///<summary> ///Loads the class properties available in style for the gtkObject widget //</summary> private System.Object LoadClassProperties(ref System.Object uiObject, Part part, Style style) { string className = Voc.MapsOnCls(part.Class); Type classType = GuiAssembly.GetType(className); IEnumerator enumProps = style.GetClassProperties(part.Class); while(enumProps.MoveNext()) { Property p = (Property)enumProps.Current; uiObject = ApplyProperty(ref uiObject, p, part, classType); } return uiObject; }
private void AddDefaultProperties(Part part, Style style) { // find the part's default properties ArrayList defaultProps = new ArrayList(); DClass cls = (DClass) Voc.DClasses[part.Class]; foreach (DProperty prop in cls.Children) { if (prop.IsDefaultProperty && !part.HasProperty(prop.Identifier, style)) style.AddProperty(prop.DefaultProperty, part); } }
///<summary> /// Applies several properties to an individual concrete widget instance. /// It implements two stages: /// - In the first stage the widget properties are applied completely dynamic: /// relying on the reflection mechanisms the Style properties are queried and loaded /// - When the first stage fails, another method is called using ad hoc knowledge /// about the widget and its properties ///</summary> protected System.Object ApplyProperties(System.Object uiObject, Part part, Style style) { //should be provided by another "component" instead of by a function: //this way the structure can be reused more easily AddDefaultProperties(part, style); if (part.Class == "HBox") { int k = 0; } try { LoadAdHocProperties(ref uiObject, part, style); LoadPartProperties(ref uiObject, part); LoadNamedProperties(ref uiObject, part, style); LoadClassProperties(ref uiObject, part, style); LoadAdHocPropertiesAfter(ref uiObject, part, style); } catch(MappingNotFoundException mnfe) { Console.WriteLine("Could not find appropriate mapping: " + mnfe.ToString()); if(m_stopOnError) #if COMPACT //TODO ; #else Environment.Exit(0); #endif } return uiObject; }
/* Moved to super class ///<summary> /// Dissects the method information for a specific property ///</summary> ///<param name="baseT"></param> ///<param name="newT"></param> ///<param name="retType"></param> ///<param name="nextValue"></param> private MemberInfo ResolveProperty(Type baseT, String newT, out Type retType, ref System.Object nextValue) { MemberInfo m = baseT.GetProperty(newT); if(m == null) { m = baseT.GetMethod(newT, new Type[0]); retType = ((MethodInfo)m).ReturnType; nextValue = ((MethodInfo)m).Invoke(nextValue, null); } else { retType = ((PropertyInfo)m).PropertyType; nextValue = ((PropertyInfo)m).GetValue(nextValue, null); } return m; }*/ ///<summary> /// Applies several properties to an individual concrete widget instance /// relying on hard-coded knowledge about the widgets ///</summary> ///<todo> // Change to the .custom format, like used for the gtk# bindings ///</todo> protected override System.Object LoadAdHocProperties(ref System.Object uiObject, Part part, Style s) { // TODO -> use this method to automatically set properties for specific classes (such as multiline for Text) return uiObject; }