//==============================================================================
bool KeyPressMappingSet::restoreFromXml (const XmlElement& xmlVersion)
{
    if (xmlVersion.hasTagName ("KEYMAPPINGS"))
    {
        if (xmlVersion.getBoolAttribute ("basedOnDefaults", true))
        {
            // if the XML was created as a set of differences from the default mappings,
            // (i.e. by calling createXml (true)), then we need to first restore the defaults.
            resetToDefaultMappings();
        }
        else
        {
            // if the XML was created calling createXml (false), then we need to clear all
            // the keys and treat the xml as describing the entire set of mappings.
            clearAllKeyPresses();
        }

        forEachXmlChildElement (xmlVersion, map)
        {
            const CommandID commandId = map->getStringAttribute ("commandId").getHexValue32();

            if (commandId != 0)
            {
                const KeyPress key (KeyPress::createFromDescription (map->getStringAttribute ("key")));

                if (map->hasTagName ("MAPPING"))
                {
                    addKeyPress (commandId, key);
                }
                else if (map->hasTagName ("UNMAPPING"))
                {
                    if (containsMapping (commandId, key))
                        removeKeyPress (key);
                }
            }
        }

        return true;
    }

    return false;
}
void KeyPressMappingSet::addKeyPress (const CommandID commandID,
                                      const KeyPress& newKeyPress,
                                      int insertIndex) throw()
{
    // If you specify an upper-case letter but no shift key, how is the user supposed to press it!?
    // Stick to lower-case letters when defining a keypress, to avoid ambiguity.
    jassert (! (CharacterFunctions::isUpperCase (newKeyPress.getTextCharacter())
                 && ! newKeyPress.getModifiers().isShiftDown()));

    if (findCommandForKeyPress (newKeyPress) != commandID)
    {
        removeKeyPress (newKeyPress);

        if (newKeyPress.isValid())
        {
            for (int i = mappings.size(); --i >= 0;)
            {
                if (mappings.getUnchecked(i)->commandID == commandID)
                {
                    mappings.getUnchecked(i)->keypresses.insert (insertIndex, newKeyPress);

                    sendChangeMessage (this);
                    return;
                }
            }

            const ApplicationCommandInfo* const ci = commandManager->getCommandForID (commandID);

            if (ci != 0)
            {
                CommandMapping* const cm = new CommandMapping();
                cm->commandID = commandID;
                cm->keypresses.add (newKeyPress);
                cm->wantsKeyUpDownCallbacks = (ci->flags & ApplicationCommandInfo::wantsKeyUpDownCallbacks) != 0;

                mappings.add (cm);
                sendChangeMessage (this);
            }
        }
    }
}