Ejemplo n.º 1
0
        public CustomPropertiesWidget(PListScheme scheme)
        {
            Scheme      = scheme ?? PListScheme.Empty;
            CurrentTree = new Dictionary <PObject, PListScheme.SchemaItem> ();
            treeview    = new PopupTreeView(this)
            {
                DoubleBuffered = true
            };
            treeview.HeadersClickable = true;

            RefreshKeyStore();
            PackStart(treeview, true, true, 0);
            FindOrAddNewEntry(TreeIter.Zero);
            ShowAll();

            var keyRenderer = new CellRendererCombo();

            keyRenderer.Editable        = true;
            keyRenderer.Model           = keyStore;
            keyRenderer.Mode            = CellRendererMode.Editable;
            keyRenderer.TextColumn      = 0;
            keyRenderer.EditingStarted += KeyRendererEditingStarted;
            keyRenderer.Edited         += KeyRendererEditingFinished;
            var col = new TreeViewColumn();

            col.Resizable = true;
            col.Title     = GettextCatalog.GetString("Property");
            col.PackStart(keyRenderer, true);
            col.SetCellDataFunc(keyRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer = (CellRendererCombo)cell;
                string id    = (string)tree_model.GetValue(iter, 0) ?? "";
                var obj      = (PObject)tree_model.GetValue(iter, 1);
                if (obj == null)
                {
                    renderer.Text      = id;
                    renderer.Editable  = false;
                    renderer.Sensitive = false;
                    return;
                }

                var key            = (PListScheme.SchemaItem)tree_model.GetValue(iter, 2);
                var parentPArray   = obj.Parent is PArray;
                renderer.Editable  = !parentPArray;
                renderer.Sensitive = !parentPArray;
                if (parentPArray)
                {
                    renderer.Text = "";
                }
                else
                {
                    renderer.Text = key != null && ShowDescriptions ? key.Description : id;
                }
            });
            treeview.AppendColumn(col);

            col = new TreeViewColumn {
                MinWidth = 25, Resizable = false, Sizing = Gtk.TreeViewColumnSizing.Fixed
            };

            var removeRenderer = new CellRendererButton(ImageService.GetPixbuf("gtk-remove", IconSize.Menu));

            removeRenderer.Clicked += RemoveElement;
            col.PackEnd(removeRenderer, false);
            col.SetCellDataFunc(removeRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                removeRenderer.Visible = treeview.Selection.IterIsSelected(iter) && !AddKeyNode.Equals(treeStore.GetValue(iter, 0));
            });

            var addRenderer = new CellRendererButton(ImageService.GetPixbuf("gtk-add", IconSize.Menu));

            addRenderer.Clicked += AddElement;
            col.PackEnd(addRenderer, false);
            col.SetCellDataFunc(addRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                addRenderer.Visible = treeview.Selection.IterIsSelected(iter) && AddKeyNode.Equals(treeStore.GetValue(iter, 0));
            });
            treeview.AppendColumn(col);

            treeview.RowActivated += delegate(object o, RowActivatedArgs args) {
                TreeIter iter;
                if (treeStore.GetIter(out iter, args.Path) && AddKeyNode.Equals(treeStore.GetValue(iter, 0)))
                {
                    AddElement(o, EventArgs.Empty);
                }
            };

            var comboRenderer = new CellRendererCombo();

            var typeModel = new ListStore(typeof(string));

            typeModel.AppendValues(PArray.Type);
            typeModel.AppendValues(PDictionary.Type);
            typeModel.AppendValues(PBoolean.Type);
            typeModel.AppendValues(PData.Type);
            typeModel.AppendValues(PData.Type);
            typeModel.AppendValues(PNumber.Type);
            typeModel.AppendValues(PString.Type);
            comboRenderer.Model      = typeModel;
            comboRenderer.Mode       = CellRendererMode.Editable;
            comboRenderer.HasEntry   = false;
            comboRenderer.TextColumn = 0;
            comboRenderer.Edited    += delegate(object o, EditedArgs args) {
                TreeIter selIter;
                if (!treeStore.GetIterFromString(out selIter, args.Path))
                {
                    return;
                }

                PObject oldObj = (PObject)treeStore.GetValue(selIter, 1);
                if (oldObj != null && oldObj.TypeString != args.NewText)
                {
                    oldObj.Replace(PObject.Create(args.NewText));
                }
            };

            treeview.AppendColumn(GettextCatalog.GetString("Type"), comboRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer           = (CellRendererCombo)cell;
                var value              = (string)tree_model.GetValue(iter, 0);
                var obj                = (PObject)tree_model.GetValue(iter, 1);
                var key                = (PListScheme.SchemaItem)tree_model.GetValue(iter, 2);
                renderer.Editable      = key == null && !AddKeyNode.Equals(value);
                renderer.ForegroundGdk = Style.Text(renderer.Editable ? StateType.Normal : StateType.Insensitive);
                renderer.Text          = obj == null ? "" : obj.TypeString;
            });

            var propRenderer = new CellRendererCombo();

            propRenderer.Model           = valueStore;
            propRenderer.Mode            = CellRendererMode.Editable;
            propRenderer.TextColumn      = 0;
            propRenderer.EditingStarted += PropRendererEditingStarted;
            propRenderer.Edited         += PropRendererEditingFinished;

            treeview.AppendColumn(GettextCatalog.GetString("Value"), propRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer = (CellRendererCombo)cell;
                var obj      = (PObject)tree_model.GetValue(iter, 1);

                renderer.Sensitive = obj != null && !(obj is PDictionary || obj is PArray || obj is PData);
                renderer.Editable  = renderer.Sensitive;
                if (!renderer.Sensitive)
                {
                    renderer.Text = "";
                    return;
                }

                if (ShowDescriptions)
                {
                    var identifier = (string)tree_model.GetValue(iter, 0);
                    var values     = PListScheme.AvailableValues(obj, CurrentTree);
                    var item       = values == null ? null : values.FirstOrDefault(v => v.Identifier == identifier);
                    if (item != null)
                    {
                        renderer.Text = item.Description ?? item.Identifier;
                        return;
                    }
                }

                switch (obj.TypeString)
                {
                case PDictionary.Type:
                    renderer.Text = string.Format(GettextCatalog.GetPluralString("({0} item)", "({0} items)", ((PDictionary)obj).Count), ((PDictionary)obj).Count);
                    break;

                case PArray.Type:
                    renderer.Text = string.Format(GettextCatalog.GetPluralString("({0} item)", "({0} items)", ((PArray)obj).Count, ((PArray)obj).Count));
                    break;

                case PBoolean.Type:
                    renderer.Text = ((PBoolean)obj).Value ? GettextCatalog.GetString("Yes") : GettextCatalog.GetString("No");
                    break;

                case PData.Type:
                    renderer.Text = string.Format("byte[{0}]", ((PData)obj).Value.Length);
                    break;

                default:
                    if (obj is IPValueObject)
                    {
                        renderer.Text = (((IPValueObject)obj).Value ?? "").ToString();
                    }
                    else
                    {
                        renderer.Sensitive = false;
                        renderer.Text      = GettextCatalog.GetString("Could not render {0}.", obj.GetType().Name);
                    }
                    break;
                }
            });
            treeview.EnableGridLines = TreeViewGridLines.Horizontal;
            treeview.Model           = treeStore;
        }
Ejemplo n.º 2
0
        public CustomPropertiesWidget(PListScheme scheme)
        {
            this.scheme = scheme = scheme ?? PListScheme.Empty;
            treeview    = new PopupTreeView(this);
            treeview.HeadersClickable = true;
            this.PackStart(treeview, true, true, 0);
            ShowAll();

            var keyRenderer = new CellRendererCombo();

            keyRenderer.Editable   = true;
            keyRenderer.Model      = keyStore;
            keyRenderer.Mode       = CellRendererMode.Editable;
            keyRenderer.TextColumn = 0;
            keyRenderer.Edited    += delegate(object o, EditedArgs args) {
                TreeIter selIter;
                if (!treeStore.GetIterFromString(out selIter, args.Path))
                {
                    return;
                }
                if (args.NewText == (string)treeStore.GetValue(selIter, 0))
                {
                    return;
                }

                var obj = (PObject)treeStore.GetValue(selIter, 1);

                var dict = obj.Parent as PDictionary;
                if (dict == null)
                {
                    return;
                }

                var key    = scheme.Keys.FirstOrDefault(k => k.Identifier == args.NewText || k.Description == args.NewText);
                var newKey = key != null ? key.Identifier : args.NewText;

                dict.ChangeKey(obj, newKey, key == null || obj.TypeString == key.Type ? null : CreateNewObject(key.Type));
            };
            var col = new TreeViewColumn();

            col.Resizable = true;
            col.Title     = GettextCatalog.GetString("Property");
            col.PackStart(keyRenderer, true);
            col.SetCellDataFunc(keyRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer = (CellRendererCombo)cell;
                string id    = (string)tree_model.GetValue(iter, 0) ?? "";
                var obj      = (PObject)tree_model.GetValue(iter, 1);
                if (obj == null)
                {
                    renderer.Text      = id;
                    renderer.Editable  = false;
                    renderer.Sensitive = false;
                    return;
                }

                var key            = scheme.GetKey(id);
                renderer.Editable  = !(obj.Parent is PArray);
                renderer.Sensitive = true;
                renderer.Text      = key != null && ShowDescriptions ? GettextCatalog.GetString(key.Description) : id;
            });
            treeview.AppendColumn(col);

            var iconSize = IconSize.Menu;

            col = new TreeViewColumn {
                MinWidth = 25, Resizable = true, Sizing = Gtk.TreeViewColumnSizing.Autosize
            };

            var removeRenderer = new CellRendererButton(ImageService.GetPixbuf("gtk-remove", IconSize.Menu));

            removeRenderer.Clicked += delegate {
                TreeIter iter;
                bool     hasSelection = treeview.Selection.GetSelected(out iter);
                PObject  obj          = null;
                if (hasSelection)
                {
                    obj = (PObject)treeStore.GetValue(iter, 1);
                    obj.Remove();
                }
            };
            col.PackEnd(removeRenderer, false);
            col.SetCellDataFunc(removeRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                removeRenderer.Visible = treeview.Selection.IterIsSelected(iter) && !AddKeyNode.Equals(treeStore.GetValue(iter, 0));
            });

            var addRenderer = new CellRendererButton(ImageService.GetPixbuf("gtk-add", IconSize.Menu));

            addRenderer.Clicked += delegate {
                Gtk.TreeIter iter = Gtk.TreeIter.Zero;
                if (!treeview.Selection.GetSelected(out iter))
                {
                    return;
                }

                PObject obj = null;
                if (treeStore.IterParent(out iter, iter))
                {
                    obj = (PObject)treeStore.GetValue(iter, 1);
                }
                obj = obj ?? nsDictionary;

                var newObj = new PString("");
                if (obj is PArray)
                {
                    var arr = (PArray)obj;
                    arr.Add(newObj);
                }
                else if (obj is PDictionary)
                {
                    string name = "newNode";
                    var    dict = (PDictionary)obj;
                    while (dict.ContainsKey(name))
                    {
                        name += "_";
                    }
                    dict.Add(name, newObj);
                }
                else
                {
                    return;
                }
            };

            col.PackEnd(addRenderer, false);
            col.SetCellDataFunc(addRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                addRenderer.Visible = treeview.Selection.IterIsSelected(iter) && AddKeyNode.Equals(treeStore.GetValue(iter, 0));
            });
            treeview.AppendColumn(col);

            treeview.RowExpanded += delegate(object o, RowExpandedArgs args) {
                var obj = (PObject)treeStore.GetValue(args.Iter, 1);
                expandedObjects.Add(obj);
            };
            treeview.RowCollapsed += delegate(object o, RowCollapsedArgs args) {
                var obj = (PObject)treeStore.GetValue(args.Iter, 1);
                expandedObjects.Remove(obj);
            };
            var comboRenderer = new CellRendererCombo();

            var typeModel = new ListStore(typeof(string));

            typeModel.AppendValues("Array");
            typeModel.AppendValues("Dictionary");
            typeModel.AppendValues("Boolean");
            typeModel.AppendValues("Data");
            typeModel.AppendValues("Date");
            typeModel.AppendValues("Number");
            typeModel.AppendValues("String");
            comboRenderer.Model      = typeModel;
            comboRenderer.Mode       = CellRendererMode.Editable;
            comboRenderer.HasEntry   = false;
            comboRenderer.TextColumn = 0;
            comboRenderer.Edited    += delegate(object o, EditedArgs args) {
                TreeIter selIter;
                if (!treeStore.GetIterFromString(out selIter, args.Path))
                {
                    return;
                }

                PObject oldObj = (PObject)treeStore.GetValue(selIter, 1);
                if (oldObj != null && oldObj.TypeString != args.NewText)
                {
                    oldObj.Replace(CreateNewObject(args.NewText));
                }
            };

            treeview.AppendColumn(GettextCatalog.GetString("Type"), comboRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer = (CellRendererCombo)cell;
                string id    = (string)tree_model.GetValue(iter, 0) ?? "";
                var key      = scheme.GetKey(id);
                var obj      = (PObject)tree_model.GetValue(iter, 1);
                if (obj == null)
                {
                    renderer.Editable = false;
                    renderer.Text     = "";
                    return;
                }
                renderer.Editable      = key == null;
                renderer.ForegroundGdk = Style.Text(renderer.Editable ? StateType.Normal : StateType.Insensitive);
                renderer.Text          = obj.TypeString;
            });

            var propRenderer = new CellRendererCombo();

            propRenderer.Model           = valueStore;
            propRenderer.Mode            = CellRendererMode.Editable;
            propRenderer.TextColumn      = 0;
            propRenderer.EditingStarted += delegate(object o, EditingStartedArgs args) {
                valueStore.Clear();
                if (Scheme == null)
                {
                    return;
                }
                TreeIter iter;
                if (!treeStore.GetIterFromString(out iter, args.Path))
                {
                    return;
                }
                var pObject = (PObject)treeStore.GetValue(iter, 1);
                if (pObject == null)
                {
                    return;
                }
                var key = Parent != null?Scheme.GetKey(pObject.Parent.Key) : null;

                if (key != null)
                {
                    var descr = new List <string> (key.Values.Select(v => v.Description));
                    descr.Sort();
                    foreach (var val in descr)
                    {
                        valueStore.AppendValues(val);
                    }
                }
            };

            propRenderer.Edited += delegate(object o, EditedArgs args) {
                TreeIter iter;
                if (!treeStore.GetIterFromString(out iter, args.Path))
                {
                    return;
                }
                var pObject = (PObject)treeStore.GetValue(iter, 1);
                if (pObject == null)
                {
                    return;
                }
                string newText = args.NewText;
                var    key     = Parent != null?Scheme.GetKey(pObject.Parent.Key) : null;

                if (key != null)
                {
                    foreach (var val in key.Values)
                    {
                        if (newText == val.Description)
                        {
                            newText = val.Identifier;
                            break;
                        }
                    }
                }
                pObject.SetValue(newText);
            };

            /*		propRenderer.EditingStarted += delegate(object o, EditingStartedArgs args) {
             *                      TreeIter iter;
             *                      if (!treeStore.GetIterFromString (out iter, args.Path))
             *                              return;
             *                      PObject obj = (PObject)treeStore.GetValue (iter, 1);
             *                      if (obj is PBoolean) {
             *                              ((PBoolean)obj).Value = !((PBoolean)obj).Value;
             *                              propRenderer.StopEditing (false);
             *                      }
             *              };*/


            treeview.AppendColumn(GettextCatalog.GetString("Value"), propRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
                var renderer = (CellRendererCombo)cell;
                var obj      = (PObject)tree_model.GetValue(iter, 1);
                if (obj == null)
                {
                    renderer.Editable = false;
                    renderer.Text     = "";
                    return;
                }
                renderer.Editable = !(obj is PArray || obj is PDictionary || obj is PData);
                obj.RenderValue(this, renderer);
            });
            treeview.EnableGridLines = TreeViewGridLines.Horizontal;
            treeview.Model           = treeStore;
        }
Ejemplo n.º 3
0
		public CustomPropertiesWidget (PListScheme scheme)
		{
			this.scheme = scheme = scheme ?? PListScheme.Empty;
			treeview = new PopupTreeView  (this);
			treeview.HeadersClickable = true;
			this.PackStart (treeview, true, true, 0);
			ShowAll ();
			
			var keyRenderer = new CellRendererCombo ();
			keyRenderer.Editable = true;
			keyRenderer.Model = keyStore;
			keyRenderer.Mode = CellRendererMode.Editable;
			keyRenderer.TextColumn = 0;
			keyRenderer.Edited += delegate(object o, EditedArgs args) {
				TreeIter selIter;
				if (!treeStore.GetIterFromString (out selIter, args.Path)) 
					return;
				if (args.NewText == (string)treeStore.GetValue (selIter, 0))
					return;
				
				var obj = (PObject)treeStore.GetValue (selIter, 1);
				
				var dict = obj.Parent as PDictionary;
				if (dict == null)
					return;
				
				var key = scheme.Keys.FirstOrDefault (k => k.Identifier == args.NewText || k.Description == args.NewText);
				var newKey = key != null ? key.Identifier : args.NewText;
				
				dict.ChangeKey (obj, newKey, key == null || obj.TypeString == key.Type ? null : CreateNewObject (key.Type));
			};
			var col = new TreeViewColumn ();
			col.Resizable = true;
			col.Title = GettextCatalog.GetString ("Property");
			col.PackStart (keyRenderer, true);
			col.SetCellDataFunc (keyRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				string id = (string)tree_model.GetValue (iter, 0) ?? "";
				var obj = (PObject)tree_model.GetValue (iter, 1);
				if (obj == null) {
					renderer.Text = id;
					renderer.Editable = false;
					renderer.Sensitive = false;
					return;
				}
				
				var key = scheme.GetKey (id);
				renderer.Editable = !(obj.Parent is PArray);
				renderer.Sensitive = true;
				renderer.Text = key != null && ShowDescriptions ? GettextCatalog.GetString (key.Description) : id;
			});
			treeview.AppendColumn (col);
			
			var iconSize = IconSize.Menu;
			col = new TreeViewColumn { MinWidth = 25, Resizable = true, Sizing = Gtk.TreeViewColumnSizing.Autosize };
			
			var removeRenderer = new CellRendererButton (ImageService.GetPixbuf ("gtk-remove", IconSize.Menu));
			removeRenderer.Clicked += delegate {
				TreeIter iter;
				bool hasSelection = treeview.Selection.GetSelected (out iter);
				PObject obj = null;
				if (hasSelection) {
					obj = (PObject)treeStore.GetValue (iter, 1);
					obj.Remove ();
				}
			};
			col.PackEnd (removeRenderer, false);
			col.SetCellDataFunc (removeRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				removeRenderer.Visible = treeview.Selection.IterIsSelected (iter) && !AddKeyNode.Equals (treeStore.GetValue (iter, 0));
			});
			
			var addRenderer = new CellRendererButton (ImageService.GetPixbuf ("gtk-add", IconSize.Menu));
			addRenderer.Clicked += delegate {
				Gtk.TreeIter iter = Gtk.TreeIter.Zero;
				if (!treeview.Selection.GetSelected (out iter))
					return;
				
				PObject obj = null;
				if (treeStore.IterParent (out iter, iter))
					obj = (PObject) treeStore.GetValue (iter, 1);
				obj = obj ?? nsDictionary;

				var newObj = new PString ("");
				if (obj is PArray) {
					var arr = (PArray) obj;
					arr.Add (newObj);
				} else if (obj is PDictionary) {
					string name = "newNode";
					var dict = (PDictionary) obj;
					while (dict.ContainsKey (name))
						name += "_";
					dict.Add (name ,newObj);
				} else {
					return;
				}
			};
			
			col.PackEnd (addRenderer, false);
			col.SetCellDataFunc (addRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				addRenderer.Visible = treeview.Selection.IterIsSelected (iter) && AddKeyNode.Equals (treeStore.GetValue (iter, 0));
			});
			treeview.AppendColumn (col);
			
			treeview.RowExpanded += delegate(object o, RowExpandedArgs args) {
				var obj = (PObject)treeStore.GetValue (args.Iter, 1);
				expandedObjects.Add (obj);
			};
			treeview.RowCollapsed += delegate(object o, RowCollapsedArgs args) {
				var obj = (PObject)treeStore.GetValue (args.Iter, 1);
				expandedObjects.Remove (obj);
			};
			var comboRenderer = new CellRendererCombo ();
			
			var typeModel = new ListStore (typeof (string));
			typeModel.AppendValues ("Array");
			typeModel.AppendValues ("Dictionary");
			typeModel.AppendValues ("Boolean");
			typeModel.AppendValues ("Data");
			typeModel.AppendValues ("Date");
			typeModel.AppendValues ("Number");
			typeModel.AppendValues ("String");
			comboRenderer.Model = typeModel;
			comboRenderer.Mode = CellRendererMode.Editable;
			comboRenderer.HasEntry = false;
			comboRenderer.TextColumn = 0;
			comboRenderer.Edited += delegate(object o, EditedArgs args) {
				TreeIter selIter;
				if (!treeStore.GetIterFromString (out selIter, args.Path)) 
					return;
				
				PObject oldObj = (PObject)treeStore.GetValue (selIter, 1);
				if (oldObj != null && oldObj.TypeString != args.NewText)
					oldObj.Replace (CreateNewObject (args.NewText));
			};
			
			treeview.AppendColumn (GettextCatalog.GetString ("Type"), comboRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				string id = (string)tree_model.GetValue (iter, 0) ?? "";
				var key   = scheme.GetKey (id);
				var obj   = (PObject)tree_model.GetValue (iter, 1);
				if (obj == null) {
					renderer.Editable = false;
					renderer.Text = "";
					return; 
				}
				renderer.Editable = key == null;
				renderer.ForegroundGdk = Style.Text (renderer.Editable ? StateType.Normal : StateType.Insensitive);
				renderer.Text = obj.TypeString;
			});
			
			var propRenderer = new CellRendererCombo ();
			
			propRenderer.Model = valueStore;
			propRenderer.Mode = CellRendererMode.Editable;
			propRenderer.TextColumn = 0;
			propRenderer.EditingStarted += delegate(object o, EditingStartedArgs args) {
				valueStore.Clear ();
				if (Scheme == null)
					return;
				TreeIter iter;
				if (!treeStore.GetIterFromString (out iter, args.Path)) 
					return;
				var pObject = (PObject)treeStore.GetValue (iter, 1);
				if (pObject == null)
					return;
				var key = Parent != null? Scheme.GetKey (pObject.Parent.Key) : null;
				if (key != null) {
					var descr = new List<string> (key.Values.Select (v => v.Description));
					descr.Sort ();
					foreach (var val in descr) {
						valueStore.AppendValues (val);
					}
				}
			};
			
			propRenderer.Edited += delegate(object o, EditedArgs args) {
				TreeIter iter;
				if (!treeStore.GetIterFromString (out iter, args.Path)) 
					return;
				var pObject = (PObject)treeStore.GetValue (iter, 1);
				if (pObject == null)
					return;
				string newText = args.NewText;
				var key = Parent != null? Scheme.GetKey (pObject.Parent.Key) : null;
				if (key != null) {
					foreach (var val in key.Values) {
						if (newText == val.Description) {
							newText = val.Identifier;
							break;
						}
					}
				}
				pObject.SetValue (newText);
			};
			
	/*		propRenderer.EditingStarted += delegate(object o, EditingStartedArgs args) {
				TreeIter iter;
				if (!treeStore.GetIterFromString (out iter, args.Path)) 
					return;
				PObject obj = (PObject)treeStore.GetValue (iter, 1);
				if (obj is PBoolean) {
					((PBoolean)obj).Value = !((PBoolean)obj).Value;
					propRenderer.StopEditing (false);
				}
			};*/
			
			
			treeview.AppendColumn (GettextCatalog.GetString ("Value"), propRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				var obj      = (PObject)tree_model.GetValue (iter, 1);
				if (obj == null) {
					renderer.Editable = false;
					renderer.Text = "";
					return;
				}
				renderer.Editable = !(obj is PArray || obj is PDictionary || obj is PData);
				obj.RenderValue (this, renderer);
			});
			treeview.EnableGridLines = TreeViewGridLines.Horizontal;
			treeview.Model = treeStore;
		}
		public CustomPropertiesWidget (PListScheme scheme)
		{
			Scheme = scheme ?? PListScheme.Empty;
			CurrentTree = new Dictionary<PObject, PListScheme.SchemaItem> ();
			treeview = new PopupTreeView  (this) { DoubleBuffered = true };
			treeview.HeadersClickable = true;
			
			RefreshKeyStore ();
			PackStart (treeview, true, true, 0);
			FindOrAddNewEntry (TreeIter.Zero);
			ShowAll ();

			var keyRenderer = new CellRendererCombo ();
			keyRenderer.Editable = true;
			keyRenderer.Model = keyStore;
			keyRenderer.Mode = CellRendererMode.Editable;
			keyRenderer.TextColumn = 0;
			keyRenderer.EditingStarted += KeyRendererEditingStarted;
			keyRenderer.Edited += KeyRendererEditingFinished;
			var col = new TreeViewColumn ();
			col.Resizable = true;
			col.Title = GettextCatalog.GetString ("Property");
			col.PackStart (keyRenderer, true);
			col.SetCellDataFunc (keyRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				string id = (string)tree_model.GetValue (iter, 0) ?? "";
				var obj = (PObject)tree_model.GetValue (iter, 1);
				if (obj == null) {
					renderer.Text = id;
					renderer.Editable = false;
					renderer.Sensitive = false;
					return;
				}
				
				var key = (PListScheme.SchemaItem) tree_model.GetValue (iter, 2);
				var parentPArray = obj.Parent is PArray;
				renderer.Editable = !parentPArray;
				renderer.Sensitive = !parentPArray;
				if (parentPArray)
					renderer.Text = "";
				else
					renderer.Text = key != null && ShowDescriptions ? key.Description : id;
			});
			treeview.AppendColumn (col);
			
			col = new TreeViewColumn { MinWidth = 25, Resizable = false, Sizing = Gtk.TreeViewColumnSizing.Fixed };
				
			var removeRenderer = new CellRendererButton (ImageService.GetPixbuf ("gtk-remove", IconSize.Menu));
			removeRenderer.Clicked += RemoveElement;
			col.PackEnd (removeRenderer, false);
			col.SetCellDataFunc (removeRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				removeRenderer.Visible = treeview.Selection.IterIsSelected (iter) && !AddKeyNode.Equals (treeStore.GetValue (iter, 0));
			});
			
			var addRenderer = new CellRendererButton (ImageService.GetPixbuf ("gtk-add", IconSize.Menu));
			addRenderer.Clicked += AddElement;
			col.PackEnd (addRenderer, false);
			col.SetCellDataFunc (addRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				addRenderer.Visible = treeview.Selection.IterIsSelected (iter) && AddKeyNode.Equals (treeStore.GetValue (iter, 0));
			});
			treeview.AppendColumn (col);
			
			treeview.RowActivated += delegate(object o, RowActivatedArgs args) {
				TreeIter iter;
				if (treeStore.GetIter (out iter, args.Path) && AddKeyNode.Equals (treeStore.GetValue (iter, 0)))
					AddElement (o, EventArgs.Empty);
			};

			var comboRenderer = new CellRendererCombo ();
			
			var typeModel = new ListStore (typeof (string));
			typeModel.AppendValues (PArray.Type);
			typeModel.AppendValues (PDictionary.Type);
			typeModel.AppendValues (PBoolean.Type);
			typeModel.AppendValues (PData.Type);
			typeModel.AppendValues (PData.Type);
			typeModel.AppendValues (PNumber.Type);
			typeModel.AppendValues (PString.Type);
			comboRenderer.Model = typeModel;
			comboRenderer.Mode = CellRendererMode.Editable;
			comboRenderer.HasEntry = false;
			comboRenderer.TextColumn = 0;
			comboRenderer.Edited += delegate(object o, EditedArgs args) {
				TreeIter selIter;
				if (!treeStore.GetIterFromString (out selIter, args.Path)) 
					return;
				
				PObject oldObj = (PObject)treeStore.GetValue (selIter, 1);
				if (oldObj != null && oldObj.TypeString != args.NewText)
					oldObj.Replace (PObject.Create (args.NewText));
			};
			
			treeview.AppendColumn (GettextCatalog.GetString ("Type"), comboRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				var value = (string) tree_model.GetValue (iter, 0);
				var obj   = (PObject)tree_model.GetValue (iter, 1);
				var key   = (PListScheme.SchemaItem)tree_model.GetValue (iter, 2);
				renderer.Editable = key == null && !AddKeyNode.Equals (value);
				renderer.ForegroundGdk = Style.Text (renderer.Editable ? StateType.Normal : StateType.Insensitive);
				renderer.Text = obj == null ? "" : obj.TypeString;
			});
			
			var propRenderer = new CellRendererCombo ();
			
			propRenderer.Model = valueStore;
			propRenderer.Mode = CellRendererMode.Editable;
			propRenderer.TextColumn = 0;
			propRenderer.EditingStarted += PropRendererEditingStarted;
			propRenderer.Edited += PropRendererEditingFinished;

			treeview.AppendColumn (GettextCatalog.GetString ("Value"), propRenderer, delegate(TreeViewColumn tree_column, CellRenderer cell, TreeModel tree_model, TreeIter iter) {
				var renderer = (CellRendererCombo)cell;
				var obj      = (PObject)tree_model.GetValue (iter, 1);

				renderer.Sensitive = obj != null && !(obj is PDictionary || obj is PArray || obj is PData);
				renderer.Editable = renderer.Sensitive;
				if (!renderer.Sensitive) {
					renderer.Text = "";
					return;
				}
				
				if (ShowDescriptions) {
					var identifier = (string) tree_model.GetValue (iter, 0);
					var values = PListScheme.AvailableValues (obj, CurrentTree);
					var item = values == null ? null : values.FirstOrDefault (v => v.Identifier == identifier);
					if (item != null && obj is IPValueObject) {
						// Ensure that we only display the Description if the items value matches the description/identifier.
						// For example when setting the Document Type Name we wish to display whatever identifer the user types
						// in and not the literal string 'Document Type Name'. However for somegthing like UISupportedDeviceOrientations
						// we can safely display the description 'iPhone' or 'iPad' and not hide important information.
						var actualValue = ((IPValueObject) obj).Value;
						if (actualValue  != null && (actualValue.ToString () == item.Description || actualValue.ToString () == item.Identifier)) {
							renderer.Text = item.Description ?? item.Identifier;
							return;
						}
					}
				}

				switch (obj.TypeString) {
				case PDictionary.Type:
					renderer.Text = string.Format (GettextCatalog.GetPluralString ("({0} item)", "({0} items)", ((PDictionary)obj).Count), ((PDictionary)obj).Count);
					break;
				case PArray.Type:
					renderer.Text = string.Format (GettextCatalog.GetPluralString ("({0} item)", "({0} items)", ((PArray)obj).Count, ((PArray)obj).Count));
					break;
				case PBoolean.Type:
					renderer.Text = ((PBoolean)obj).Value ? GettextCatalog.GetString ("Yes") : GettextCatalog.GetString ("No");
					break;
				case PData.Type:
					renderer.Text = string.Format ("byte[{0}]", ((PData)obj).Value.Length);
					break;
				default:
					if (obj is IPValueObject) {
						renderer.Text = (((IPValueObject)obj).Value ?? "").ToString ();
					} else {
						renderer.Sensitive = false;
						renderer.Text = GettextCatalog.GetString ("Could not render {0}.", obj.GetType ().Name);
					}
					break;
				}
			});
			treeview.EnableGridLines = TreeViewGridLines.Horizontal;
			treeview.Model = treeStore;
		}