Пример #1
0
        /// <summary>
        /// Writes serialized KmlItem into writer
        /// </summary>
        /// <param name="writer">Writer used to write serialized item.</param>
        /// <param name="item">Item for serialization.</param>
        /// <param name="indent">Default indent.</param>
        public static void WriteItem(TextWriter writer, KmlItem item, int indent)
        {
            bool ghost = item is KmlGhostNode;

            if (!ghost)
            {
                writer.WriteLine(item.ToLine(indent));
            }
            if (item is KmlNode)
            {
                int     newIndent = indent;
                KmlNode node      = (KmlNode)item;
                if (!ghost)
                {
                    writer.WriteLine(new KmlBegin().ToLine(indent));
                    newIndent = indent + 1;
                }
                foreach (KmlItem child in node.AllItems)
                {
                    WriteItem(writer, child, newIndent);
                }
                if (!ghost)
                {
                    writer.WriteLine(new KmlEnd().ToLine(indent));
                }
            }
        }
Пример #2
0
        private void AddAttrib(KmlNode toItem, KmlAttrib beforeItem)
        {
            KmlNode node = toItem;
            string  input;
            string  preset = "";
            bool    loop   = true;

            while (loop && DlgInput.Show("Enter the name for the new attribute:", "NEW attribute", Icons.Add, preset, out input))
            {
                string attrib = input;
                if (attrib.Length > 0 && attrib.IndexOf('=') < 0)
                {
                    attrib = attrib + "=";
                }
                KmlItem item = KmlItem.CreateItem(attrib);
                if (item is KmlAttrib && beforeItem != null)
                {
                    node.InsertBefore(beforeItem, (KmlAttrib)item);
                    loop = false;
                    // View will be refreshed in AttribChanged event
                }
                else if (item is KmlAttrib)
                {
                    node.Add((KmlAttrib)item);
                    loop = false;
                    // View will be refreshed in AttribChanged event
                }
                else
                {
                    DlgMessage.Show("Attribute name is not allowed to be empty or contain following characters: {}", "NEW attribute", Icons.Warning);
                    preset = input;
                    // Input will pop up again while loop == true
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Load a KML structure from data file into tree.
        /// </summary>
        /// <param name="filename">The full path and filename of the data file to read</param>
        public void Load(string filename)
        {
            Tree.Items.Clear();
            TreeDetails.Items.Clear();

            KmlRoots = KmlItem.ParseFile(filename);

            // Check if any of these roots is not a node
            // If so, pack all roots into a new ghost root
            if (KmlRoots.Any(x => !(x is KmlNode)))
            {
                KmlGhostNode root = new KmlGhostNode(System.IO.Path.GetFileName(filename), null);
                root.AddRange(KmlRoots);
                KmlRoots.Clear();
                KmlRoots.Add(root);
            }

            foreach (KmlItem item in KmlRoots)
            {
                if (item is KmlNode)
                {
                    Tree.Items.Add(new GuiTreeNode((KmlNode)item));
                }
            }

            if (Tree.Items.Count >= 1)
            {
                TreeViewItem item = (TreeViewItem)Tree.Items[0];
                item.IsSelected = true;
                if (Tree.Items.Count == 1)
                {
                    item.IsExpanded = true;
                }
            }
        }
Пример #4
0
        private void AddChildNode(KmlNode toItem, KmlNode beforeItem)
        {
            KmlNode node = toItem;
            string  input;
            string  preset = "";
            bool    loop   = true;

            while (loop && DlgInput.Show("Enter the tag for the new node:", "NEW node", Icons.Add, preset, out input))
            {
                KmlItem item = KmlItem.CreateItem(input);
                if (item is KmlNode && beforeItem != null)
                {
                    node.InsertBefore(beforeItem, (KmlNode)item);
                    loop = false;
                    // View will be refreshed in ChildrenChanged event
                }
                else if (item is KmlNode)
                {
                    node.Add((KmlNode)item);
                    loop = false;
                    // View will be refreshed in ChildrenChanged event
                }
                else
                {
                    DlgMessage.Show("Tag is not allowed to be empty or contain following characters: ={}", "NEW node", Icons.Warning);
                    preset = input;
                    // Input will pop up again while loop == true
                }
            }
        }
Пример #5
0
 /// <summary>
 /// Deletes a KmlItem from this nodes lists.
 /// Result will be false if item was not in the lists or couldn't be deleted
 /// because of restrictions.
 /// </summary>
 /// <param name="item">The KmlItem to delete</param>
 /// <returns>True if item was deleted, false otherwise</returns>
 public virtual bool Delete(KmlItem item)
 {
     if (!item.CanBeDeleted)
     {
         return(false);
     }
     // Call itme's Delete to call it's BeforeDelete()
     // But there would usually be called this method,
     // to avoid loop we set parent to null.
     // We also ignore result, will be false in that case
     RemapParent(item, null);
     item.Delete();
     if (!AllItems.Remove(item))
     {
         // It wasn't in the list, nothing to do
         return(false);
     }
     if (item is KmlAttrib)
     {
         bool result = Attribs.Remove((KmlAttrib)item);
         InvokeAttribChanged();
         return(result);
     }
     else if (item is KmlNode)
     {
         bool result = Children.Remove((KmlNode)item);
         InvokeChildrenChanged();
         return(result);
     }
     else
     {
         return(Unknown.Remove(item));
     }
 }
Пример #6
0
        /// <summary>
        /// Creates a KmlItem from a string.
        /// This is used for adding items outside of loading from file.
        /// Result will be a KmlAttrib, KmlNode, KmlVessel, etc. or null
        /// if line is "{", "}" or empty
        /// </summary>
        /// <param name="line">The line to build a KmlItem from</param>
        /// <returns>A KmlItem derived object</returns>
        public static KmlItem CreateItem(string line)
        {
            if (line == null || line.Length == 0)
            {
                return(null);
            }
            else if (line.IndexOf('{') >= 0)
            {
                return(null);
            }
            else if (line.IndexOf('}') >= 0)
            {
                return(null);
            }

            KmlItem item = ParseLine(line);

            if (item is KmlAttrib)
            {
                return(item);
            }
            else
            {
                // It's a node
                return(ParseNode(item));
            }
        }
Пример #7
0
 /// <summary>
 /// Adds each KmlItem in the list before KmlItem like InsertBefore(KmlItem, KmlItem) does.
 /// <see cref="KML.KmlNode.InsertBefore(KML.KmlItem, KML.KmlItem)"/>
 /// </summary>
 /// <param name="beforeItem">The KmlItem where the new item should be inserted before</param>
 /// <param name="list">A List of KmlItem to add</param>
 public void InsertBeforeRange(KmlItem beforeItem, List <KmlItem> list)
 {
     foreach (KmlItem item in list)
     {
         Add(beforeItem, item);
     }
 }
Пример #8
0
        /// <summary>
        /// Select should be called from within other GuiManagers
        /// and wants this manager to get avtive and go to given item.
        /// </summary>
        /// <param name="item">The KmlItem to select</param>
        /// <returns>Whether item was found or not</returns>
        public bool Select(KmlItem item)
        {
            KmlNode masterNode = item is KmlNode ? (KmlNode)item : item.Parent;

            foreach (GuiKerbalsNode node in KerbalsList.Items)
            {
                if (node.DataKerbal == masterNode)
                {
                    // Force a refreh, by causing SelectionChanged to invoke
                    KerbalsList.SelectedItem = null;
                    KerbalsList.SelectedItem = node;
                    KerbalsList.ScrollIntoView(node);
                    Focus();
                    if (item is KmlAttrib)
                    {
                        foreach (GuiTreeAttrib attrib in KerbalsDetails.Items)
                        {
                            if (attrib.DataAttrib == item)
                            {
                                attrib.IsSelected = true;
                                KerbalsDetails.Focus();
                            }
                        }
                    }
                    return(true);
                }
            }
            return(false);
        }
Пример #9
0
        private static void WriteFile(StreamWriter file, KmlItem item, int indent)
        {
            bool ghost = item is KmlGhostNode;

            if (!ghost)
            {
                file.WriteLine(item.ToLine(indent));
            }
            if (item is KmlNode)
            {
                int     newIndent = indent;
                KmlNode node      = (KmlNode)item;
                if (!ghost)
                {
                    file.WriteLine(new KmlBegin().ToLine(indent));
                    newIndent = indent + 1;
                }
                foreach (KmlItem child in node.AllItems)
                {
                    WriteFile(file, child, newIndent);
                }
                if (!ghost)
                {
                    file.WriteLine(new KmlEnd().ToLine(indent));
                }
            }
        }
Пример #10
0
        private bool SelectSearch(Stack <KmlNode> stack, KmlItem item)
        {
            KmlNode node = stack.Peek();

            foreach (KmlItem sub in node.AllItems)
            {
                if (sub == item)
                {
                    return(true);
                }
                else if (sub is KmlNode)
                {
                    stack.Push(sub as KmlNode);
                    if (SelectSearch(stack, item))
                    {
                        return(true);
                    }
                    else
                    {
                        stack.Pop();
                    }
                }
            }
            return(false);
        }
Пример #11
0
        private void KerbalsList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            // Store currently selected attribute, in case we just unselect + select the current item to refresh
            if (KerbalsList.SelectedItem == null)
            {
                // We're unselcting, this is the old data we want to restore in future call of this event
                GuiTreeAttrib attrib = (KerbalsDetails.SelectedItem as GuiTreeAttrib);
                if (attrib == null)
                {
                    _oldSelectedAttrib         = null;
                    _alternativeSelectedAttrib = null;
                }
                else
                {
                    _oldSelectedAttrib = attrib.DataAttrib;
                    int i = KerbalsDetails.SelectedIndex;
                    if (i < KerbalsDetails.Items.Count - 1)
                    {
                        _alternativeSelectedAttrib = (KerbalsDetails.Items[i + 1] as GuiTreeAttrib).DataAttrib;
                    }
                    else if (i > 0)
                    {
                        _alternativeSelectedAttrib = (KerbalsDetails.Items[i - 1] as GuiTreeAttrib).DataAttrib;
                    }
                    else
                    {
                        _alternativeSelectedAttrib = null;
                    }
                }
            }

            KerbalsDetails.Items.Clear();
            if (KerbalsList.SelectedItem != null)
            {
                GuiKerbalsNode Node = (GuiKerbalsNode)KerbalsList.SelectedItem;
                KerbalsDetails.ContextMenu = Node.ContextMenu;
                foreach (KmlAttrib attrib in Node.DataKerbal.Attribs)
                {
                    KerbalsDetails.Items.Add(new GuiTreeAttrib(attrib));
                }
                _oldSelectedKerbal = Node.DataKerbal;

                // Restore attrib selection
                if (Node.DataKerbal == _oldSelectedKerbal && _oldSelectedAttrib != null)
                {
                    if (!Select(_oldSelectedAttrib))
                    {
                        Select(_alternativeSelectedAttrib);
                    }
                    if (KerbalsDetails.SelectedItem != null)
                    {
                        (KerbalsDetails.SelectedItem as ListViewItem).Focus();
                    }
                }
            }
            else
            {
                KerbalsDetails.ContextMenu = null;
            }
        }
Пример #12
0
        /// <summary>
        /// Adds a child KmlItem to this nodes lists of children, depending of its
        /// derived class KmlNode or KmlAttrib or further derived from these.
        /// When an KmlAttrib "Name" is found, its value will be used for the "Name" property
        /// of this node.
        /// </summary>
        /// <param name="item">The KmlItem to add</param>
        public virtual void Add(KmlItem item)
        {
            AllItems.Add(item);
            if (item is KmlNode)
            {
                Children.Add((KmlNode)item);
            }
            else if (item is KmlAttrib)
            {
                KmlAttrib attrib = (KmlAttrib)item;
                if (attrib.Name.ToLower() == "name")
                {
                    Name = attrib.Value;

                    // Get notified when Name changes
                    attrib.AttribValueChanged += Name_Changed;
                    attrib.CanBeDeleted        = false;
                }
                Attribs.Add(attrib);
            }
            else
            {
                Unknown.Add(item);
                Syntax.Warning(this, "Unknown line in persistence file: " + item.ToString());
            }
        }
Пример #13
0
        /// <summary>
        /// Show a search dialog.
        /// </summary>
        /// <param name="left">The left coordinate for the dialog</param>
        /// <param name="top">The top coordinate for the dialog</param>
        /// <param name="selectedItem">Out: Returns the selected KmlItem if "Ok" was clicked, null otherwise</param>
        /// <param name="presetText">The preset text to search for</param>
        /// <returns>True if "Ok" was clicked, false otherwise</returns>
        public static bool Show(double left, double top, out KmlItem selectedItem, string presetText = null)
        {
            DlgSearch dlg = new DlgSearch(presetText);

            dlg.Left = left;
            dlg.Top  = top;
            return(dlg.Show(out selectedItem));
        }
Пример #14
0
        private static List <KmlItem> ParseFile(System.IO.StreamReader file, KmlNode parent)
        {
            List <KmlItem> list = new List <KmlItem>();

            string line;

            while ((line = file.ReadLine()) != null)
            {
                KmlItem newItem = ParseLine(line);
                if (newItem is KmlBegin)
                {
                    KmlItem lastItem;
                    int     l = list.Count - 1;
                    if (l < 0)
                    {
                        lastItem = new KmlItem("");
                    }
                    else
                    {
                        lastItem = list[l];
                        list.RemoveAt(l);
                    }
                    KmlNode newNode = new KmlNode(lastItem, parent);
                    if (newNode.Tag.ToLower() == "vessel")
                    {
                        newNode = new KmlVessel(newNode);
                    }
                    else if (newNode.Tag.ToLower() == "kerbal")
                    {
                        newNode = new KmlKerbal(newNode);
                    }
                    else if (newNode.Tag.ToLower() == "part")
                    {
                        newNode = new KmlPart(newNode);
                    }
                    else if (newNode.Tag.ToLower() == "resource")
                    {
                        newNode = new KmlResource(newNode);
                    }
                    list.Add(newNode);
                    newNode.AddRange(ParseFile(file, newNode));
                }
                else if (newItem is KmlEnd)
                {
                    Identify(list);
                    return(list);
                }
                else
                {
                    list.Add(newItem);
                }
            }

            Identify(list);
            return(list);
        }
Пример #15
0
        /// <summary>
        /// Get previous result from last search.
        /// </summary>
        /// <returns>The previous KmlItem from search</returns>
        public static KmlItem SearchPrevious()
        {
            int i = _searchResults.IndexOf(_selectedItem);

            if (i > 0 && i < _searchResults.Count)
            {
                _selectedItem = _searchResults[i - 1];
            }
            return(_selectedItem);
        }
Пример #16
0
        /// <summary>
        /// Get next result from last search.
        /// </summary>
        /// <returns>The next KmlItem from search</returns>
        public static KmlItem SearchNext()
        {
            int i = _searchResults.IndexOf(_selectedItem);

            if (i >= 0 && i < _searchResults.Count - 1)
            {
                _selectedItem = _searchResults[i + 1];
            }
            return(_selectedItem);
        }
Пример #17
0
        /// <summary>
        /// Adds a child KmlItem to this nodes lists of children, depending of its
        /// derived class KmlNode, KmlAttrib or further derived from these.
        /// When an KmlAttrib "Name", "Type" or "Trait" are found, their value
        /// will be used for the corresponding property of this node.
        /// </summary>
        /// <param name="beforeItem">The KmlItem where the new item should be inserted before</param>
        /// <param name="newItem">The KmlItem to add</param>
        protected override void Add(KmlItem beforeItem, KmlItem newItem)
        {
            if (newItem is KmlAttrib)
            {
                KmlAttrib attrib = (KmlAttrib)newItem;
                if (attrib.Name.ToLower() == "name" && Name.Length == 0)
                {
                    // Name property is managed by KmlNode,
                    // but we need another method to be called on name change event
                    // to rename the crew attrib in assigned vessel part also
                    attrib.AttribValueChanged += CrewName_Changed;
                }
                else if (attrib.Name.ToLower() == "type" && Type.Length == 0)
                {
                    Type = attrib.Value;

                    // Get notified when Type changes
                    attrib.AttribValueChanged += Type_Changed;
                    attrib.CanBeDeleted        = false;
                }
                else if (attrib.Name.ToLower() == "trait" && Trait.Length == 0)
                {
                    Trait = attrib.Value;

                    // Get notified when Trait changes
                    attrib.AttribValueChanged += Trait_Changed;
                    attrib.CanBeDeleted        = false;
                }
                else if (attrib.Name.ToLower() == "state" && State.Length == 0)
                {
                    State = attrib.Value;

                    // Get notified when State changes
                    attrib.AttribValueChanged += State_Changed;
                    attrib.CanBeDeleted        = false;
                }
                else if (attrib.Name.ToLower() == "brave" && Brave == 0.0)
                {
                    Brave = GetDoubleValue(attrib.Value, Brave);

                    // Get notified when Trait changes
                    attrib.AttribValueChanged += Brave_Changed;
                    attrib.CanBeDeleted        = false;
                }
                else if (attrib.Name.ToLower() == "dumb" && Dumb == 0.0)
                {
                    Dumb = GetDoubleValue(attrib.Value, Dumb);

                    // Get notified when Dumb changes
                    attrib.AttribValueChanged += Dumb_Changed;
                    attrib.CanBeDeleted        = false;
                }
            }
            base.Add(beforeItem, newItem);
        }
Пример #18
0
 private void SearchAddItem(List <KmlItem> result, KmlItem item, string text, bool checkNodeTag, bool checkNodeText, bool checkAttribName, bool checkAttribValue)
 {
     if (SearchCheckItem(item, text, checkNodeTag, checkNodeText, checkAttribName, checkAttribValue))
     {
         result.Add(item);
     }
     if (SearchCheckItem(item, text, true, true, true, true))
     {
         _oldSearchList.Add(item);
     }
 }
Пример #19
0
 /// <summary>
 /// Some key was pressed.
 /// </summary>
 public void CommandExec(string Command)
 {
     if (TreeDetails.IsKeyboardFocusWithin && TreeDetails.SelectedItem is GuiTreeAttrib)
     {
         if (Command == "Enter")
         {
             // Enter the TextBox for value editing
             TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);
             (TreeDetails.SelectedItem as ListViewItem).MoveFocus(request);
         }
         else if (Command == "Escape" || Command == "Left")
         {
             // Get back to TreeView
             Tree.Focus();
             (Tree.SelectedItem as TreeViewItem).Focus();
         }
         else
         {
             (TreeDetails.SelectedItem as GuiTreeAttrib).CommandExec(Command);
         }
     }
     else if (TreeDetails.IsKeyboardFocusWithin)
     {
         // Empty details
         if (Command == "Left")
         {
             // Get back to TreeView
             Tree.Focus();
             (Tree.SelectedItem as TreeViewItem).Focus();
         }
     }
     else if (Tree.IsKeyboardFocusWithin && Tree.SelectedItem is GuiTreeNode)
     {
         if (Command == "Enter" && TreeDetails.HasItems)
         {
             // Switch to attributes
             TreeDetails.Focus();
             KmlItem item = GetSelectedItem();
             if (item is KmlNode)
             {
                 KmlNode node = (KmlNode)item;
                 if (node.Attribs.Count > 0)
                 {
                     Select(node.Attribs[0]);
                     (TreeDetails.SelectedItem as ListViewItem).Focus();
                 }
             }
         }
         else
         {
             (Tree.SelectedItem as GuiTreeNode).CommandExec(Command);
         }
     }
 }
Пример #20
0
 private static void Identify(List <KmlItem> list)
 {
     for (int i = 0; i < list.Count; i++)
     {
         KmlItem item        = list[i];
         KmlItem replaceItem = item.Identify();
         if (replaceItem != null)
         {
             list[i] = replaceItem;
         }
     }
 }
Пример #21
0
 /// <summary>
 /// Select should be called from within other GuiManagers
 /// and wants this manager to get avtive and go to given item.
 /// </summary>
 /// <param name="item">The KmlItem to select</param>
 public void Select(KmlItem item)
 {
     foreach (GuiVesselsNode node in VesselsList.Items)
     {
         if (node.DataVessel == item)
         {
             VesselsList.SelectedItem = node;
             VesselsList.ScrollIntoView(node);
             Focus();
             return;
         }
     }
 }
Пример #22
0
 /// <summary>
 /// Changes the parent. Needed when a node is changed to a derived class
 /// and all existing children need to have a new parent.
 /// </summary>
 /// <param name="item">The KmlItem where parent needs to be changed</param>
 /// <param name="parent">The new parent KmlNode</param>
 protected static void RemapParent(KmlItem item, KmlNode parent)
 {
     if (item.Parent != parent)
     {
         // This often happens when we iterate through the lists,
         // so we can not delete items from that list here.
         // TODO KmlItem.RemapParent(): Delete item from old parent
         // item.Delete(); // from previous parent
         item.UnbindOldParent();
         item.Parent = parent;
         item.IdentifyParent();
     }
 }
Пример #23
0
        private void ButtonPrevious_Click(object sender, RoutedEventArgs e)
        {
            KmlItem search = DlgSearch.SearchPrevious();

            if (search != null)
            {
                TabsManager.TreeManager.Select(search);
            }
            else
            {
                TabsManager.Previous();
            }
        }
Пример #24
0
 /// <summary>
 /// Select should be called from within other GuiManagers
 /// and wants this manager to get avtive and go to given item.
 /// </summary>
 /// <param name="item">The KmlItem to select</param>
 public void Select(KmlItem item)
 {
     foreach (GuiWarningsNode node in WarningsList.Items)
     {
         if (node.DataMessage.Source == item)
         {
             WarningsList.SelectedItem = node;
             WarningsList.ScrollIntoView(node);
             Focus();
             return;
         }
     }
 }
Пример #25
0
 /// <summary>
 /// Select should be called from within other GuiManagers
 /// and wants this manager to get avtive and go to given item.
 /// </summary>
 /// <param name="item">The KmlItem to select</param>
 public void Select(KmlItem item)
 {
     foreach (GuiKerbalsNode node in KerbalsList.Items)
     {
         if (node.DataKerbal == item)
         {
             KerbalsList.SelectedItem = node;
             KerbalsList.ScrollIntoView(node);
             Focus();
             return;
         }
     }
 }
Пример #26
0
        private void AttribCopy_Click(object sender, RoutedEventArgs e)
        {
            KmlAttrib attrib = ((sender as MenuItem).DataContext as KmlAttrib);

            var sr = new StringWriter();

            KmlItem.WriteItem(sr, attrib, 0);

            sr.Flush();

            var textNode = sr.GetStringBuilder().ToString();

            Clipboard.SetDataObject(textNode);
        }
Пример #27
0
 /// <summary>
 /// Select should be called from within other GuiManagers
 /// and wants this manager to get avtive and go to given item.
 /// </summary>
 /// <param name="item">The KmlItem to select</param>
 public void Select(KmlItem item)
 {
     foreach (GuiWarningsNode node in WarningsList.Items)
     {
         if (node.DataMessage.Source == item)
         {
             // Force a refreh, by causing SelectionChanged to invoke
             WarningsList.SelectedItem = null;
             WarningsList.SelectedItem = node;
             WarningsList.ScrollIntoView(node);
             Focus();
             return;
         }
     }
 }
Пример #28
0
 /// <summary>
 /// Select should be called from within other GuiManagers
 /// and wants this manager to get avtive and go to given item.
 /// </summary>
 /// <param name="item">The KmlItem to select</param>
 public void Select(KmlItem item)
 {
     foreach (GuiVesselsNode node in VesselsList.Items)
     {
         if (node.DataVessel == item)
         {
             // Force a refreh, by causing SelectionChanged to invoke
             VesselsList.SelectedItem = null;
             VesselsList.SelectedItem = node;
             VesselsList.ScrollIntoView(node);
             Focus();
             return;
         }
     }
 }
Пример #29
0
        /// <summary>
        /// Search all child nodes of this node for a certain tag and name,
        /// create one if not found. Does not search recursive.
        /// </summary>
        /// <param name="tag">The tag of the KmlNode to search for</param>
        /// <param name="name">The name of the KmlNode to search for</param>
        /// <returns>The found or created KmlNode</returns>
        public KmlNode GetOrCreateChildNode(string tag, string name)
        {
            KmlNode node = GetChildNode(tag, name);

            if (node == null)
            {
                node = KmlItem.CreateItem(tag) as KmlNode;
                if (name != null && name.Length > 0)
                {
                    // Add name attribute
                    node.Add(KmlItem.CreateItem("name=" + name));
                }
                Add(node);
            }
            return(node);
        }
Пример #30
0
        /// <summary>
        /// Search all KmlAttribs of this node, create one if not found.
        /// Does not search recursive. Default value will only be used on creation.
        /// </summary>
        /// <param name="name">The name of the KmlAttribs to search for</param>
        /// <param name="defaultValue">The default value for a created attribute</param>
        /// <returns>The found or created KmlAttrib</returns>
        public KmlAttrib GetOrCreateAttrib(string name, string defaultValue)
        {
            KmlAttrib attrib = GetAttrib(name);

            if (attrib == null)
            {
                string line = name + "=";
                if (defaultValue != null && defaultValue.Length > 0)
                {
                    line += defaultValue;
                }
                attrib = KmlItem.CreateItem(line) as KmlAttrib;
                Add(attrib);
            }
            return(attrib);
        }